以前也做react-navigation与redux的整合,不过那时候react native以及react-navigation的版本都不高,前些天在做新项目时用的是rn0.54版本,react-navigation是1.3.0版本,当我按照低版本的方法进行整合时缺报错了,让我措不及防,踩过的坑还要再踩一遍...
相信大家对于redux都很熟悉,不再介绍有关redux的知识
报错如下:
整合错误代码如下:
navigation={addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav,
})}
/>
最后查看react-navigation源码发现原来createNavigationContainer.js文件里的render方法里多出了一个addListener属性,源码如下:
react-navigation 1.0.0-beta.11版本 react native 0.46版本
render() { let navigation = this.props.navigation; if (this._isStateful()) { if (!this._navigation || this._navigation.state !== this.state.nav) { this._navigation = addNavigationHelpers({ dispatch: this.dispatch, state: this.state.nav, }); } navigation = this._navigation; } returnreact-navigation 1.3.0版本 react native 0.54版本{...this.props} navigation={navigation} />; }
render() { let navigation = this.props.navigation; if (this._isStateful()) { const nav = this.state.nav; invariant(nav, 'should be set in constructor if stateful'); if (!this._navigation || this._navigation.state !== nav) { this._navigation = addNavigationHelpers({ dispatch: this.dispatch, state: nav, addListener: (eventName, handler) => { if (eventName !== 'action') { return { remove: () => {} }; } this._actionEventSubscribers.add(handler); return { remove: () => { this._actionEventSubscribers.delete(handler); }, }; }, }); } navigation = this._navigation; } invariant(navigation, 'failed to get navigation'); return{...this.props} navigation={navigation} />; }
好了,已经知道原因了,不过再加上addListener属性后还是会报错,下面介绍具体做法:
1. 需要引用 react-navigation-redux-helpers中间插件,安装命令如下:
npm install react-navigation-redux-helpers --save
2.
import { createReduxBoundAddListener, createReactNavigationReduxMiddleware, } from 'react-navigation-redux-helpers';
createReduxBoundAddListener: 创建监听器
createReactNavigationReduxMiddleware: 创建中间件
特别注意: createReactNavigationReduxMiddleware 一定要在运行createReduxBoundAddListener之前运行
附上代码:
// Note: createReactNavigationReduxMiddleware must be run before createReduxBoundAddListener const middleware = createReactNavigationReduxMiddleware( "App", state => state.nav, ); export const addListener = createReduxBoundAddListener("App"); const middleWares = [middleware]; export default applyMiddleware(...middleWares)(createStore)(reducers);
附上目录结构:
App.js
import React, { Component } from 'react'; import {Provider} from 'react-redux'; import store from './src/store'; import NavigatorPages from './src/AllPages/TabNavigatorPage'; type Props = {}; export default class App extends Component{ render() { return ( store={store}> ); } }
store.js
import {createStore,applyMiddleware} from 'redux'; import { createReduxBoundAddListener, createReactNavigationReduxMiddleware, } from 'react-navigation-redux-helpers'; //reducers import reducers from './Allreducer/index'; // Note: createReactNavigationReduxMiddleware must be run before createReduxBoundAddListener const middleware = createReactNavigationReduxMiddleware( "App", state => state.nav, ); export const addListener = createReduxBoundAddListener("App"); const middleWares = [middleware]; export default applyMiddleware(...middleWares)(createStore)(reducers);
AllPages/TabNavigatorPage.js
import React, { Component } from 'react'; import FirstPage from './FirstPage'; import SecondPage from './SecondPage'; import ThirdPage from './ThirdPage'; import FourthPage from './FourthPage'; import {connect} from 'react-redux'; import { TabNavigator, addNavigationHelpers, } from 'react-navigation'; import {addListener} from '../store'; class NavigatorPages extends Component{ constructor(props){ super(props); } render(){ alert(this.props.nav.index); return(navigation={addNavigationHelpers({ dispatch: this.props.dispatch, state: this.props.nav, addListener })} /> ) } } export const SimpleAppNavigator = TabNavigator({ page1: {screen: FirstPage}, page2: {screen: SecondPage}, page3: {screen: ThirdPage}, page4: {screen: FourthPage} },{ initialRouteName: 'page1', swipeEnabled: true, animationEnabled: true, lazy: false, tabBarPosition:'bottom', }); const mapStateToProps = (store)=>({ nav : store.TabNavigatorReducer, }); export default connect(mapStateToProps)(NavigatorPages);
AllReducer/TabNavigatorReducer.js
import {SimpleAppNavigator} from '../AllPages/TabNavigatorPage'; export default (state,action)=>{ //获取并返回新的state var newState = SimpleAppNavigator.router.getStateForAction(action,state) ; return newState || state; }
AllReducer/index.js
import { combineReducers } from 'redux'; import TabNavigatorReducer from './TabNavigatorReducer'; const reducers = combineReducers({ TabNavigatorReducer }); export default reducers;
下面那四个路由页面可自行创建,都是很简单的页面,不过下面还是给出代码
AllPages/FirstPage.js
import React, { Component } from 'react'; import { StyleSheet, Text, View, } from 'react-native'; export default class SecondPage extends Component { static navigationOptions = { tabBarLabel: '页面1', //drawerLabel:'页面1' }; render() { return (style={styles.container}> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, textView: { fontSize: 16, textAlign: 'center', margin: 10, color:'red' }, });style={styles.welcome}> This is First Page!
AllPages/SecondPage.js
import React, { Component } from 'react'; import { StyleSheet, Text, View, } from 'react-native'; export default class SecondPage extends Component{ static navigationOptions = { tabBarLabel: '页面2', //drawerLabel:'页面2' }; render() { return ( style={styles.container}> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, textView: { fontSize: 16, textAlign: 'center', margin: 10, color:'red' }, });style={styles.welcome}> This is Second Page!
AllPages/ThirdPage.js
import React, { Component } from 'react'; import { StyleSheet, Text, View, } from 'react-native'; export default class ThirdPage extends Component{ static navigationOptions = { tabBarLabel: '页面3', //drawerLabel:'页面3' }; render() { return ( style={styles.container}> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, textView: { fontSize: 16, textAlign: 'center', margin: 10, color:'red' }, });style={styles.welcome}> This is Third Page!
AllPages/FourthPages.js
import React, { Component } from 'react'; import { StyleSheet, Text, View, } from 'react-native'; export default class FourthPage extends Component{ static navigationOptions = { tabBarLabel: '页面4', //drawerLabel:'页面4' }; render() { return ( style={styles.container}> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, textView: { fontSize: 16, textAlign: 'center', margin: 10, color:'red' }, });style={styles.welcome}> This is Fourth Page!
附上运行效果: