react-native+reduxを触り始めてそんなに経ってませんので備忘録
react-navigationのStateをreduxで管理しようという試みです。
公式リファレンスだとコードが一箇所にまとめられてて
パッと見わかりづらかったのでメモ(自分だけ?)
1. Navigationのコンポーネントを作成
今回の例だとこんな感じ
Navigation.js
import {
StackNavigator
} from 'react-navigation';
import screens from './screens';
export default StackNavigator({
Splash: {
screen: screens.Splash,
navigationOptions: {
header: null,
}
},
MainScreen: {
screen: screens.MainScreen,
navigationOptions: {
title: 'メイン画面',
headerBackTitle: null,
}
},
DetailScreen: {
screen: screens.EventScreen,
navigationOptions: {
title: '詳細画面',
}
}
})
スプラッシュ画面→メイン画面←→詳細画面
みたいな構成だと仮定。
2. NavigationのStateを加工するReducerを作成
これはほぼ公式通りに作れば良さそう。
getStateForAction
がよしなにNavigationのStateを作ってくれる。
navReducer.js
import nav from './Navigation'; //(1)で作ったやつ
// 初期画面名を指定して初期ステートを作成
const initialState = nav.router.getStateForAction(nav.router.getActionForPathAndParams('Splash'));
export default (state = initialState, action) => {
const nextState = nav.router.getStateForAction(action, state);
return nextState || state;
};
3. StoreにReducerを渡す
Store.js
import navReducer from './reducers/navReducer';
const appReducer = combineReducers({
nav: navReducer,
...
});
4. ReduxとのConnect(コンテナ作成)
実際は、いちいちContainerとComponentを分けなくてもよさげです。
コメントのところはフワッとした理解なので、コードを見てみようかと思います。
NavigationContainer.js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { addNavigationHelpers } from 'react-navigation';
import Navigation from '../routes/Navigation';
class Nav extends Component {
render() {
// addNavigationHelpersが生成したnavigationが、
// actionをdispatchしてくれて
// reducerが新しいNavigationのStateを作って
// 新しいStateでNavigationが更新されるという仕組み(多分)
return (
<Navigation
navigation={addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav,
})}
/>
);
}
}
const mapStateToProps = (state, ownProps) => ({
nav: state.nav
});
export default connect(mapStateToProps)(Nav);
5. Providerの中でコンテナを使う
普通のreduxのように使えばOK
App.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Navigation from './containers/NavigationContainer';
export default class App extends Component {
render() {
return (
<Provider store={store}>
<Navigation />
</Provider>
);
}
}
もうちょっと掘り下げて色々やってみようかと思います。
react-native-router-fluxからもうまく移行できるようなやり方を模索中です。