React Native
セットアップ
ドキュメント
https://www.udemy.com/react-native-the-practical-guide/learn/v4/t/lecture/8567846?start=0
仕組み
UI コンポーネントは、Native コンポーネントにコンパイルされる。 ロジックは独自のスレッドで JS のママで実行される。 JS の実行には Safari の JavaScriptCore や Chrome の V8 が使われる。
使用できる JavaScript の構文については下記を参照すること。 https://facebook.github.io/react-native/docs/javascript-environment
Android で動かす
- JDK をインストールする
- 環境変数を設定する
- JAVA_HOME
C:\Program Files\Java\jdk1.8.0_181
- ANDROID_HOME
C:\Users\Shota\AppData\Local\Android\Sdk
- PATH
C:\Users\Shota\AppData\Local\Android\Sdk\platform-tools
- JAVA_HOME
adb reverse tcp:8081 tcp:8081
を実行するyarn eject
で Eject する(Eject しないとサードパーティのライブラリは使えない)
エミュレータで動かす
- Android Studio の Tools – Android – AVD Manager からエミュレータを作成する。
- 必要なバージ ョンの SDK がインストールされていないとエラーが出るので、適宜追加でインストールする
yarn android
を実行すると、React Native のコードが Java にコンパイルされ、エミュレータでアプリが立ち上がるadb not found
というメッセージが出た場合は、adb.exe にパスが通っているか確認すること。
実機で動かす
- PC と Android を接続し、USB デバッグを有効にしたうえで、
yarn android
を実行する。
iPhone で動かす
- 必要になったときにレクチャー21,22を参照すること
ビルドに失敗したとき
/android/app/build
をまるごと消して、もう一度 sync してみるとうまくいくかも
Typescript 環境のセットアップ
下記を参考にやったらできた。
https://github.com/Microsoft/TypeScript-React-Native-Starter
デバッグ
ショートカット
目的 | Android | iPhone |
---|---|---|
メニュー表示 | Ctrl + M もしくはシェイク | Ctrl + D もしくはシェイク |
リロード | R * 2 回 | Ctrl + R |
端末を回転 | Ctrl + ←→ | Ctrl + ←→ |
Console.log
デバッグメニューから Debug JS Remotely を選択する。 Console.log の内容が、Chrome のデベロッパツールに表示される。
接続できなかった場合は下記の設定を行うこと。
- Press Cmd + M on emulator screen
- Go to Dev settings > Debug server host & port for device
- Set localhost:8081
ブレークポイント
Debug JS Remotely を有効にした状態で、Chrome Dev Tools の Source タブで設定する。
react-native-debugger
react-native-debugger を使えば、Redux を含めて、あらゆるものをデバッグすることができるようになるので、必ずインストールすること。 セットアップは下記のように行う。RN のバグで、ブレークポイントが現在使えない模様。
import { createStore, compose } from 'redux';
let composeEnhancers = compose;
if (__DEV__) {
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
}
const store = createStore(reducer, composeEnhancers());
コンポーネントの作成
タッチイベント
DOM と異なり、例えば View などのオブジェクトは、デフォルトではタッチできない。タッチできるようにするにはTouchable****
コンポーネントで囲む。タッチ時の反応ごとにいくつかの種類がある。
- TouchableHighlight タッチ時に暗くする
- TouchableNativeFeedback タッチ時にネイティブエフェクトをかける(リップルなど)
- TouchableOpacity タッチ時に明るくする
- TouchableWithoutFeedback タッチ時に何もしない
<TouchableNativeFeedback onPress={props.onPress}>
<View style={styles.listItem}>some contents</View>
</TouchableNativeFeedback>
ScrollView
スクロールが必要な場合は View の替わりに ScrollView コンポーネント を使用する。 ただし、大量のデータを表示する場合は、より効率的な FlatList や SectionList を使うこと。
FlatList
- 配列を data に渡す。配列は、key というプロパティを持ったオブジェクトの配列であること。
- renderItem に表示内容を記述する。info.item で個々のオブジェクトにアクセスできる。
<FlatList
style={styles.container}
data={props.places}
renderItem={(info) => (
<ListItem
placeName={info.item.name}
onPress={() => props.onItemDeleted(info.item.key)}
/>
)}
/>
スタティック画像
jpg 画像等の静的画像を表示する方法。
- import 文で画像をインポートする。
- すると、ImageURISource というインターフェースを持つオブジェ クトが自動的に生成される。
- これを Image コンポーネントに渡す。
<Image source={importedImage} />
表示方法はデフォルトで Cover になっている。
https://facebook.github.io/react-native/docs/image#resizemode
ダイナミック画像
オンライン上の画像等の場合は、下記のように ImageURISource を手動で作成し、Image コンポーネントに渡す。
ダイナミック画像の場合は、height
と width
を指定しないと表示されないので注意すること。
{
uri: 'https://images.fineartamerica.com/some.jpg';
}
Modal
特に特記事項なし。モーダルを表示した状態でリロードすると仮想端末がハングするバグがあるので注意。
https://facebook.github.io/react-native/docs/modal
<Modal onRequestClose={() => onClose()} animationType="slide" />
スタイリング
StyleSheet
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'flex-start',
},
input: {
width: 300,
borderColor: 'gray',
borderWidth: 0,
},
});
-
flex:1 を指定すると、利用可能なすべての範囲を埋め尽くす。指定しなければ、最小限の範囲を占有する。
-
TextInput 等にはスタイルの設定項目が少ない。スタイルを設定するときは、View や ScrollView で囲んで設定する。
-
複数のスタイル
style 属性には複数のスタイルを配列で指定できる
<View style={[someStyleObject, { width: 100 }]} />
Stylesheet.create を使う意味
- Validation が行われる
- 効率的なネイティブコードに変換される
スタイルを適用できるコンポーネント
Image、ScrollView、Text、View の4つだけ
再利用可能性の高い width の指定
内部コンテンツは width100%にして、container(View など)に width80%などを指定すると、移植が楽になる。
カスタムコンポーネントとスタイルの継承
よく使うコンポーネントはカスタムコンポーネントとして用意しておくと良い(components/UI フォルダを参照)。下記は、あらかじめスタイルが設定された TextInput を作成する場合の例 。
const DefaultInput = (props: TextInputProps) => {
return (
<TextInput
{...props}
style={[
styles.input,
// コンポーネントの外側から一部のスタイルを変更できるようにする
props.style,
]}
underlineColorAndroid="transparent"
/>
);
};
const styles = StyleSheet.create({
input: {
width: '100%',
borderWidth: 1,
borderColor: '#eee',
padding: 4,
marginTop: 8,
marginBottom: 8,
},
});
Text コンポーネントのスタイル継承
Text コンポーネントを入れ子にすると、上位の Text のスタイルが配下の全ての Text に継承される。 たとえば BlackText というコンポーネントを作っておけば、これで囲むだけで配下の全ての Text が黒になる。
背景に画像を表示する
ImageBackground を使う。
https://facebook.github.io/react-native/docs/images#background-image-via-nesting
カスタムボタン
Touchable,View,Text を組み合わせて作る。
<TouchableOpacity onPress={props.onPress}>
<View {...props} style={[styles.button, { backgroundColor: props.color }]}>
<Text>{props.children}</Text>
</View>
</TouchableOpacity>
Platform API
OS の種類等によって描写を変更する際に使用する。
if (Platform.OS === 'ios') {
return (
<TouchableOpacity onPress={props.onPress}>{content} </TouchableOpacity>
);
}
return (
<TouchableNativeFeedback onPress={props.onPress}>
{content}
</TouchableNativeFeedback>
);
クロスプラットフォームな UI ライブラリ
NativeBase などを使うとよいかも。
Dimensions API
画面サイズを取得したり、ローテーションの検知をしたりする際に使用する
- Dimenstion API
- get() current dimentions
- window(※ android ではメニューバーを含まない)
- screen(※ android ではメニューバーを含む)
- listen to Dimention Changes
- addEventListener('change')
- get() current dimentions
画面の高さや幅によってスタイルを変更する 画面の高さによって State を更新するイベントリスナーを、Dimensions に登録する。
componentDidMount = () => {
this.checkWindowHeight();
Dimensions.addEventListener('change', this.checkWindowHeight);
};
componentWillUnmount = () => {
Dimensions.removeEventListener('change', this.checkWindowHeight);
};
checkWindowHeight = () => {
if (Dimensions.get('window').height > 500) {
this.setState({ hasEnoughHeight: true });
} else {
this.setState({ hasEnoughHeight: false });
}
};
コンポーネントのスタイルは、render メソッドの中で、State の状態によって動的に変更する。
const passwordsContainerStyle = {
flexDirection: hasEnoughHeight ? 'column' : 'row',
};