目次
こんにちは!個別指導塾コミット塾長、AWESOME開発担当の船津です。
今回はreduxでカウンターアプリを作ってみましょう。
どんなアプリを作るかも決まっていないのに、最近流行っていると聞いて飛びついてみました。
目標は最小限の学習コストでredux react-nativeを使ってみることです。
参考にしたサイト
http://uraway.hatenablog.com/entry/2016/02/11/220000
めちゃくちゃ簡単に書いてくださっているのでとても参考になりました。
https://github.com/alinz/example-react-native-redux/tree/master/Counter
少しわかってきたらこちらを参考にすると良いでしょう。
まずはアプリを新規作成しましょう。
react-native init PlaygroundApp
npm install --save react-redux redux
出来上がったpackage.jsonがこちら
{ "name": "PlaygroundApp", "version": "0.0.1", "private": true, "scripts": { "start": "react-native start" }, "dependencies": { "react": "15.2.1", "react-native": "0.29.0", "react-native-button": "^1.6.0", "react-redux": "^4.4.5", "redux": "^3.5.2", }, "devDependencies": {} }
index.ios.js
いつも通りアプリの登録だけ行います。
'use strict'; import React, { AppRegistry} from 'react-native'; import App from './app/containers/app'; AppRegistry.registerComponent('PlaygroundApp', () => App);
components/app.js
親コンポーネントです。
stateを管理するstoreを作成して、カウンターをインポートします。
ConuterをちゃんとProviderで囲ってstore={store}としておかないとConnectでreduxとreact-nativeを連携するところで詰まります。
ここでは簡単のためにdispatchで使用するtypeを直接指定しています。
import React, { Component } from 'react'; import { StyleSheet, View, Text, TouchableOpacity, } from 'react-native'; import counter from '../reducers/index'; import Counter from './Counter'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; const store = createStore(counter); export default class App extends Component { render() { const { counter, count } = this.props; return ( <Provider store={store}> {<Counter increment={() => store.dispatch({ type :'INCREMENT' })} decrement={() => store.dispatch({ type :'DECREMENT' })} />} </Provider> ); } }
components/Counter.js
子コンポーネントを定義します。
storeがもっている値をreactで使用するために、connectメソッドを使います。
store.getState().countなどとしても値を持ってこれますが、そのままだとstateが変更されても画面は更新されません。
connect関数の置き場所で一番ハマりました。
今回のプロジェクトではここに書いていないと動きませんでした。
import React, { Component } from 'react'; import { StyleSheet, View, Text, TouchableOpacity, } from 'react-native'; import { connect } from 'react-redux'; export default class Counter extends Component { constructor(props) { super(props); } render() { const { count, increment, decrement } = this.props; return ( <View style={styles.main}> <Text style={styles.counter}> Counter: {count} </Text> <TouchableOpacity onPress={increment} style={styles.button}> <Text style={styles.counter}> + </Text> </TouchableOpacity> <TouchableOpacity onPress={decrement} style={styles.button}> <Text style={styles.counter}> - </Text> </TouchableOpacity> </View> ); } } function mapStateToProps(state) { return { count: state.count } } function mapDispatchToProps(dispatch) { return { }; } export default connect( mapStateToProps )(Counter); const styles = StyleSheet.create({ main: { flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center', }, counter: { fontSize: 16, }, button: { width: 100, height: 30, padding: 10, backgroundColor: 'lightgray', alignItems: 'center', justifyContent: 'center', margin: 3 } });
reducers/index.js
実際のstateの変更を管理するところですね。
const initialState = { count: 0 }; export default function counter(state = initialState, action = {}){ switch(action.type){ case 'INCREMENT': console.log(state.count); return { count: state.count + 1 } case 'DECREMENT': return { count: state.count - 1 } default: return state; } }
普段jsはjqueryくらいしか触らないので、reduxをやろうと思ってから実際に書いてみるまでかなりのハードルがありました。
触ってみるとかなり面白いかったです。
reduxを作る際はreactプロジェクトの中でも特に親子関係を意識して設計しないといけない一方、作ってしまえば管理は楽です。外国語の資料ばかりですが、みなさんも是非どうぞ。