React Nativeの基本を理解することを目的とします!
スマートフォンでアプリをインストールしてください
手取り早くやるためにこっちを使います。 expo try Expo Snackを押して出て来た先ほどのアプリで読み込ませます。
おすすめ!
npm install -g create-react-native-app
create-react-native-app Native
cd Native
npm ios
npm v5はサポートされていないので要注意・・・!!
XCodeを入れておいてください!
cmd + d でメニューが開くのでデバッグもできます
実機の人の場合は端末を振るとメニューが出ます!
メンターはプロなので遠慮なく聞いてください!
brew install watchman
npm install -g react-native-cli
react-native init Native
cd Native
react-native run-ios
- Reactを用いてiOSやAndroidのネイティブアプリを構築できるフレームワーク
- JavaScriptからネイティブのAPIが呼ばれる
- 一度覚えればどのプラットフォーム向けにも書けるようになる ※ 一度書けばどのプラットフォームでも動くわけではない
- ネイティブアプリがJavaScriptで書ける
- アプリを素早くビルドできる
- CSSのサブセットがあるため、CSSでスタイリングできる
- 複雑なUIになると、ネイティブコードを書く必要がある
Reactと同じ! 一点だけ覚えるとしたら、div, spanとかwebのdomを構成するタグは使えません。 かわりに、react-nativeからコンポーンネントを読み込んで使います。
import { Text, View, StyleSheet } from 'react-native';
もう一点! CSSは使えません。代わりにCSS in JS式のスタイリングができます。
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
});
適用方法
<View style={styles.container}>
これ以降、importのところにあるAppRegistry、末尾にあるAppRegistry.registerComponentは省略します。 また、クラスの名前がみなさんで違っているかもしれませんのでご注意ください。
この中に文字を入れることはできません。
基本的に入れ物になります。
文字を入れるためのコンポーネントになります。
スタイルシートを扱うためのものです。
詳しくはこちら【React-Native】StyleSheetについて
(いいねほしい・・・)
こちらのコードを元に基本を解説して行きます。
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View
} from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone!
Save to get a shareable url. You get a new url each time you save.
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 64,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
});
import {
StyleSheet,
Text,
View
} from 'react-native';
styleSheet.createを使います。 基本はCSSと同じ。flexについては後述します。
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 64,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
});
基本はReactと同じ。 CSS in JSと同じスタイルの適用方法。 Textの中に文字を入れる。Viewの中に入れない。
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone!
Save to get a shareable url. You get a new url each time you save.
</Text>
</View>
);
}
}
若干のくせのあるスタイリング方法です。 描きコードがわかりやすいと思うのでお試しください。
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<View style={[styles.base, styles.box1]}>
<Text style={styles.text}>I am 2.</Text>
</View>
<View style={[styles.base, styles.box2]}>
<Text style={styles.text}>I am 5.</Text>
</View>
<View style={[styles.base, styles.box3]}>
<Text style={styles.text}>I am 1.</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
text: {
fontSize: 24,
color: 'white',
},
base: {
justifyContent: 'center',
alignItems: 'center',
},
box1: {
flex: 2,
backgroundColor: 'black'
},
box2: {
flex: 5,
backgroundColor: 'red',
},
box3: {
flex: 1,
backgroundColor: 'yellow',
},
});
flexは比率になります。
デフォルトでは縦方向の比率になります。
container は1なので画面全部。
containerの中身は2:5:2の比率になります。
flexの方向を切り替えたい場合は、
flexDirectionにて制御します。
この場合は、
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
},
...
とすると横方向に2:5:1の比率になります。 詳しくはこちら
justifyContent, alignItems はCSSのflexレイアウトと同じです。
続いてはTextInputを扱います。 ここからは普通の説明に加えてアプリケーションっぽいものを作って行きます。
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
} from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
}
}
_onChangeText = (text) => {
this.setState({ text });
}
render() {
const {
text,
} = this.state;
return (
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={this._onChangeText}
underlineColorAndroid="transparent"
/>
<Text>{text}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
input: {
height: 30,
width: 200,
borderBottomWidth: 1,
borderBottomColor: '#008080',
}
});
<TextInput
style={styles.input}
onChangeText={this._onChangeText}
underlineColorAndroid="transparent"
/>
onChangeTextというイベントハンドラをつけます。 すると入力した文字を受け取れますので、こちらを使ってstateを更新して行きます。 underlineColorAndroidはAndroid対策でついてます(勝手にラインが付いてしまうため)。
さっきのやつを拡張します。
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
FlatList,
} from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
list: [],
}
}
_onChangeText = (text) => {
this.setState({ text });
}
_onPress = () => {
const {
list,
text,
} = this.state;
const _list = list.concat();
_list.push({ key:text });
this.setState({
text: '',
list: _list,
});
}
render() {
const {
list,
text,
} = this.state;
return (
<View style={styles.container}>
<View style={styles.inputArea}>
<TextInput
style={styles.input}
onChangeText={this._onChangeText}
underlineColorAndroid="transparent"
value={text}
/>
<TouchableOpacity
style={styles.button}
onPress={this._onPress}
>
<Text style={styles.buttonText} >Add</Text>
</TouchableOpacity>
</View>
<FlatList
data={list}
renderItem={({item}) => <Text style={styles.itemText}>{item.key}</Text>}
style={styles.list}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
inputArea: {
flexDirection: 'row',
marginTop: 64,
},
input: {
height: 30,
width: 200,
borderBottomWidth: 1,
borderBottomColor: '#008080',
marginRight: 20,
},
button: {
width: 80,
height: 40,
backgroundColor: '#006060',
justifyContent: 'center',
alignItems: 'center',
},
buttonText: {
color: 'white',
fontSize: 20,
},
list: {
width: 300,
},
itemText: {
fontSize: 22,
margin: 10,
}
});
ボタンを実装するためには今回はTouchableOpacityを使います。 TouchableHightLightやButtonなどを使うこともできます。
<TouchableOpacity
style={styles.button}
onPress={this._onPress}
>
<Text style={styles.buttonText} >Add</Text>
</TouchableOpacity>
イベントハンドラはonPressで実装します。
TouchableOpacityは押下した時に透過度が変わりふわっとした印象を与えることができます。
今回はFlatViewを使うことで実装します。 ListViewや自前のコンポーネントを使って実装することもできます。 FlatListは非常に簡単にリストを作成し、スクロールも実装できるコンポーネントです。
<FlatList
data={list}
renderItem={({item}) => <Text style={styles.itemText}>{item.key}</Text>}
style={styles.list}
/>
dataにはstateを与えます。 この時keyを持つオブジェクトの配列として渡す必要があるので
_onPress = () => {
const {
list,
text,
} = this.state;
const _list = list.concat();
_list.push({ key:text });
this.setState({
text: '',
list: _list,
});
}
このようにします。 本来的にはkeyには一意のkeyを渡さないといけないのでtextにするのは好ましくありませんが簡略化のためにこうしました。
renderItem関数を渡します。 itemは各要素が渡る事になるので、item.keyにしてkeyを表示させることで登録したものを表示させました。
関数を渡すので、
const List = props => (
<Text style={styles.itemText}>
{props.item.key}
</Text>
)
...
<FlatList
data={list}
renderItem={List}
style={styles.list}
/>
このようにSFCで実装することも可能です。
classFunctionでは実装不可です。
todoアプリに内容を変えてみましょう。 仕様としてはタップしたら追加したアイテムが完了状態になればOKです!
みたい人だけ・・!!
<Text style={styles.lineThrough}>text</Text>
...
const styles = StyleSheet.create({
lineThrough: {
textDecorationLine: 'line-through',
}
})
TextコンポーネントにtextDecorationLine: 'line-through'を与えることで打ち消し線を実現できます。
_onPressItem = (index) => () => {
const {
list,
} = this.state;
const _list = list.concat();
_list[index].done = !_list[index].done
this.setState({
list: _list,
});
}
...
const List = props => (
<TouchableOpacity onPress={props.onPress(props.index)}>
<Text style={props.item.done ? styles.itemTextDone : styles.itemText}>
{props.item.text}
</Text>
</TouchableOpacity>
)
こうすることで押下時に押下されたものだけdoneが切り替わります。 listに追加する時にdone: falseを追加することを忘れずに・・・!! また、三項演算子を使うことでスタイルを切り替えることもできます。