React-Native入坑二:项目React-Navigation + Redux集成

严俊彦
2023-12-01

项目集成Redux + React-Navigation开发

用过React开发过项目的可能对Redux都有一定的了解吧,他和Vue中的Vuex也是比较类似的,今天这里就说说如何在RN项目中将Redux和React-Navigation进行结合集成到项目中进行开发:
注意: 由于上次说过React-Navigation,这里就默认看这篇文展是已经了解了React-Navigation的

  1. 安装相应的依赖:

yarn add redux react-redux react-thunk react-navigation-redux-helpers

  1. 在创建的路由中进行配置: (这里的路由创建在一个AppNavigator.js文件中)
// 创建路由相关
import {createAppContainer} from "react-navigation";
import {createStackNavigator} from "react-navigation-stack";
// 配置redux相关
import {createReactNavigationReduxMiddleware, createReduxContainer} from "react-navigation-redux-helpers";
import { connect } from "react-redux";
// 引入路由页面
import WelcomePage from "../page/WelcomePage";
import HomePage from "../page/HomePage";
import DetailPage from "../page/DetailPage";
// 创建路由
const MainNavigator = createStackNavigator({
  WelcomePage: {
    screen: WelcomePage,
    navigationOptions: {
      header: null
    }
  },
  HomePage: {
      screen: HomePage,
      navigationOptions: {
          header: null
      }
  },
  DetailPage: {
      screen: DetailPage
  }
})
// 这两个导出将会在创建导航的reducer中用到, rootCom为初始化的页面路由名, RootNavigator为使用createAppNavigator包装后创建出的路由导航(这是React-Navigation 3.x之后需要做的事情)
export const rootCom = "WelcomePage";
export const RootNavigator = createAppContainer(MainNavigator);

/**
 * react-native引入redux中间件第一步
 * 创建一个middleware,将navigation引入到store, key为'root'
 */
export const middleware = createReactNavigationReduxMiddleware(
  state => state.nav,
  'root'
)
/**
 * react-native引入redux中间件第二步
 */
const AppWithNavigationState = createReduxContainer(RootNavigator, 'root')
/**
 * react-native引入redux中间件第三步
 * state 到 Props的映射
 */
const mapStateToProps = state => ({
  state: state.nav
})
/**
 * react-native引入redux中间件第四步
 * 连接React 组件与 Redux store
 */
 export default connect(mapStateToProps)(AppWithNavigationState)
  1. 更改App.js中的组件内容,使用Provider包裹路由导航组件
import React from "react";
// 从react-redux引入Provider
import {Provider} from "react-redux";
// App路由导航
import AppNavigator from "./navigator/AppNavigator";
// redux store,之后会进行创建
import store from "./store";

export default class App extends React.Component {
  render(){
    return (<Provider store={store}>
      <AppNavigator />
    </Provider>)
  }
}
  1. 创建store:
// 引入创建store方法和中间件方法
import {applyMiddleware, createStore} from "redux";
import thunk from "redux-thunk";、
// 相关的reducer,这里会使用combineReducer合并多个reducer
import reducers from "../reducer";
// 引入在AppNavigation.js中创建的middleware
import {middleware} from "../navigator/AppNavigator";

/**
 * 自定义redux中间件: 用于redux中的dispatch(action)状态进行打印日志
 */
const logger = store => next => action => {
    if(typeof action === "function"){
        console.log("dispatch a function")
    }else {
        console.log("dispatch ", action)
    }
    const result = next(action);
    console.log("nextState", store.getState())
}
// 使用的中间件
const middlewares = [
    middleware,
    logger,
    thunk
]
export default createStore(reducers, applyMiddleware(...middlewares))
  1. 处理reducer:
// 用于合并多个reducer
import {combineReducers} from "redux";
// 这个是之后自己创建的reducer, 和在react web项目中使用创建是一样的
import theme from "./theme";
// 导入Navigatr中的相关内容,用于创建与路由相关的store
import {rootCom, RootNavigator} from "../navigator/AppNavigator";

/**
 * 1. 指定默认的state
 */
const navState = RootNavigator.router.getStateForAction(RootNavigator.router.getActionForPathAndParams(rootCom))

/**
 * 2. 创建自己的navigation reducer
 */
const navReducer = (state = navState, action) => {
    const nextState = RootNavigator.router.getStateForAction(action, state);
    return nextState || state;
}

/**
 * 3. 合并reducer
 */
const index = combineReducers({
    nav: navReducer,
    theme: theme
})

export default index

到这里为止就基本可以在各个页面中使用和react web项目相似的方法在各个页面中使用redux的内容了,这里再加一点就是在页面中处理物理返回键


  • 这里如果不做这个处理,当我们跳转到某个页面的时候,使用android手机上的物理返回会直接返回到手机桌面,而不是返回上一页,所以这里使用react-native中提供的BackHandler进行处理:
// 这个用于在处理物理返回键时返回上一页
import {NavigationActions} from "react-navigation";
import {
    BackHandler
} from "react-native";
// ... 其余省略
// 在组件HomePage中添加如下两个生命周期方法
class HomePage extends React.Component {
	// ... 
 	// 处理安卓的物理返回键返回上一页而不是直接返回桌面
    componentDidMount(){
        BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
    }
    componentWillUnmount() {
        BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
    }
    onBackPress = () => {
        const {dispatch, nav} = this.props;
        // 这里的[0] 或者 1 是根据自己的页面Navigation中页面的次序和当前跳转的层数来的,根究实际情况而定
        if(nav.routes[0].index === 1) {
            return false;
        }
        dispatch(NavigationActions.back());
        return true;
    }
	// ... render也省略
}

// 需要将注入到store中的nav注入到组件Props中才可以正常使用
const mapStateToProps = state => ({
    nav: state.nav
})
export default connect(mapStateToProps)(HomePage);

Over !!!

 类似资料: