react-navigation的state管理放到application統(tǒng)一的管理中嘶伟,即所謂的react-navigation和redux一體化湾蔓,或者集成捏悬。
官網(wǎng)doc介紹:https://reactnavigation.org/docs/redux-integration.html
- 添加依賴
- 編寫navReducer
- 如何實現(xiàn)一體化
- 編寫Root.js入口組件
- 物理鍵重寫
- Demo地址
添加依賴
yarn add react-navigation-redux-helpers
或
npm install --save react-navigation-redux-helpers
編寫navReducer
import {NavigationActions} from 'react-navigation'
import {AppNavigator} from "../AppNavigator";
// Start with two routes: The Main screen, with the Login screen on top.
const firstAction = AppNavigator.router.getActionForPathAndParams('Main');
const tempState = AppNavigator.router.getStateForAction(firstAction);
const secondAction = AppNavigator.router.getActionForPathAndParams('Login');
const initiaNavState = AppNavigator.router.getStateForAction(secondAction,tempState);
function nav(state=initiaNavState,action){
let nextState;
switch (action.type){
case 'Login':
nextState = AppNavigator.router.getStateForAction(
NavigationActions.back(),
state
)
break;
case 'Logout':
nextState = AppNavigator.router.getStateForAction(
NavigationActions.navigate({ routeName: 'Login' }),
state
);
break;
case 'BackTwoScreen':
const key = state.routes[state.index-1].key
nextState = AppNavigator.router.getStateForAction(
NavigationActions.back({key:key}),
state
)
break;
case 'ExitApp':
nextState = initiaNavState;
break;
default:
nextState = AppNavigator.router.getStateForAction(action, state);
break;
}
// Simply return the original `state` if `nextState` is null or undefined.
return nextState || state;
}
export default nav;
在reducers文件夾下創(chuàng)建index.js文件徊哑,將多個reducer合并硼啤。
import {combineReducers} from 'redux'
import nav from './nav'
import auth from './auth'
const AppReducers = combineReducers({
nav,
auth
})
export default AppReducers;
如何實現(xiàn)一體化
創(chuàng)建AppNavigator.js文件艰猬。
import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux'
import {addNavigationHelpers,StackNavigator,NavigationActions } from 'react-navigation'
import {addListener} from "./utils/redux";
...
export const AppNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Main: { screen: MainScreen },
Profile: { screen: ProfileScreen },
ThirdScreen: { screen: ThirdScreen },
}
)
class AppWithNavigationState extends React.Component{
static propTypes = {
dispatch:PropTypes.func.isRequired,
nav:PropTypes.object.isRequired,
}
render(){
const {dispatch,nav} = this.props;
return(
<AppNavigator
navigation = {addNavigationHelpers({
dispatch,
state:nav,
addListener
})}
/>
)
}
}
const mapStateToProps = state =>({
nav:state.nav
})
export default connect(mapStateToProps)(AppWithNavigationState);
其中/utils/redux.js文件內(nèi)容:
import {
createReactNavigationReduxMiddleware,
createReduxBoundAddListener
} from 'react-navigation-redux-helpers'
const middleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
)
const addListener = createReduxBoundAddListener('root')
export {
middleware,
addListener,
};
編寫Root.js入口組件
import React from 'react';
import {Provider} from 'react-redux'
import {createStore,applyMiddleware} from 'redux'
import AppWithNavigationState from './AppNavigator'
import {middleware} from "./utils/redux";
import AppReducers from './reducers/index'
const store = createStore(AppReducers,applyMiddleware(middleware))
export default class ReduxExampleApp extends React.Component {
render(){
return(
<Provider store = {store}>
<AppWithNavigationState/>
</Provider>
)
}
}
物理鍵重寫
在AppNavigaor.js文件中横堡,進行物理鍵監(jiān)聽
import React from 'react';
import { BackHandler,ToastAndroid } from "react-native";
import PropTypes from 'prop-types';
...
export const AppNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
...
}
)
class AppWithNavigationState extends React.Component{
...
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = ()=>{
const { dispatch, nav } = this.props;
if (nav.index === 0) {
if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
//將state設(shè)置成第一次啟動一致,避免從哪個界面退出冠桃,
啟動時顯示哪個界面的bug(殺掉進程啟動無該問題)
dispatch({type:'ExitApp'})
return false
}
ToastAndroid.show('再按一次退出!', 1000);
this.lastBackPressed = Date.now();
return true;
}
dispatch(NavigationActions.back());
return true;
}
render(){
const {dispatch,nav} = this.props;
return(
<AppNavigator
navigation = {addNavigationHelpers({
dispatch,
state:nav,
addListener
})}
/>
)
}
}
const mapStateToProps = state =>({
nav:state.nav
})
export default connect(mapStateToProps)(AppWithNavigationState);