React-Navigation与Redux整合详解

前端之家收集整理的这篇文章主要介绍了React-Navigation与Redux整合详解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

继react-navigation发布已经过去半年的时间,想必React Native的玩家早已玩转于手掌了。如果你还不了解,就out啦~还在等什么?

React Native未来导航者:react-navigation 使用详解

Redux框架给开发者带来的优势是显而易见的。它好比Android中的MVP架构一样,使得复杂的业务逻辑和视图状态变得简单、清晰。如何将react-navigation和Redux结合到一起呢?本篇博客就来唠唠。

在搞定Redux与react-navigation整合之前,我们有必要先了解下在没有使用react-navigation导航下的Redux项目架构,先来看一个简单的Redux项目目录:

一般情况下,Redux项目中都会包含如下几个目录:

(1)Action

(2)Reducer

(3)Store

熟悉Redux的玩家肯定对这三个模块肯定都不陌生。Action中负责分发用户行为;Reducer接收Action,并根据行为类型进行相应的逻辑处理,并返回最新状态;Store中负责Action和Reducer的交互,并记录Reducer处理的最新状态。并且还可以应用中间件等;此时可利用react-redux将状态与视图绑定。这样,Action -> Controller -> View就完美的形成了闭环流程。下面我们分别看下三者之间是如何衔接的。

1、Action

export let main = (url,params,isLoading,isLoadMore,isRefreshing) => {
    return dispatch => {

        // 1.发出拉取数据的信号
        dispatch(loadMainContent(isLoading,isRefreshing));

        // 2.请求网络
        return HttpUtil.fetchGet(url,(responSEObj) => {
                dispatch(receiveMainContent(responSEObj.result.bookList));
                console.info("success");
            },(error) => {
                dispatch(receiveMainContent([]));
                console.info("error" + error);
            }
        )
    }
}
let loadMainContent = (isLoading,isRefreshing) => {
    return {
        type: types.LOAD_MAIN_LIST,isLoading: isLoading,isLoadMore: isLoadMore,isRefreshing: isRefreshing
    }
}

let receiveMainContent = (mainList) => {
    return {
        type: types.GET_MAIN_LIST,mainList: mainList
    }
}
如上代码所示,在main Action中,我们定义了不同的Action行为,并通过dispatch进行分发。

2、Reducer

const initState = {
    mainList: [],isLoading: true,isLoadMore: false,isRefreshing: false
}

let mainReducer = (state = initState,action) => {
    switch (action.type) {
        case types.LOAD_MAIN_LIST:
            return Object.assign({},state,{
                isLoading: action.isLoading,isLoadMore: action.isLoadMore,isRefreshing: action.isRefreshing
            });
        case types.GET_MAIN_LIST:
            return Object.assign({},{
                isLoading: false,isRefreshing: false,mainList: state.isLoadMore ? state.mainList.concat(action.mainList) : action.mainList
            })
        default:
            return state;
    }
}
上面代码定义了对应的Reducer,用来接收Action的行为,并进行处理,最终返回最新状态State。

3、整合Reducer

export default rootReducer = combineReducers({
    Main,})

4、Store

let store = createStore(rootReducer,{},compose(
  applyMiddleware(thunk),window.devToolsExtension ? window.devToolsExtension() : f => f
))
Store相对简单,因为Redux本身没有异步概念,不能直接使用setTimeOut等,但是网络处理需要异步进行,并且结果是异步返回,所以为了处理此种情况,可以使用中间件react-thunk帮助我们完成。

5、Connect

import React,{ Component } from 'react';
import { Provider } from 'react-redux';
import App from './components/app';
import store from './store/store';

export default class Root extends Component {

    render() {
        return (
            <Provider store={store}>
                <App />
            </Provider>
        )
    }
}
使用react-redux将store传递到Provider,从而将Redux和视图层绑定在一起,完成Action -> Reducer -> Store -> View的整体连接。

上面代码中App即视图的入口,react-navigation其实就充当了程序的入口,负责视图界面之间的跳转交互。

const AppNavigator = StackNavigator(
    {
        Splash: { screen: SplashScene },}
)

在react-navigation中使用navigate来实现界面间跳转行为。此时我们可以理解为Redux中的dispatch,即一个用户行为。

1、dispatch的触发需要Reducer的接收,所以我们需要定义react-navigation的Reducer:

import Routers from './Router';

const navReducer = (state,action) => {
    const newState = Routers.router.getStateForAction(action,state);
    return newState || state;
}

export default navReducer;
Router中就是我们定义的react-navigation的StackNavigator。navReducer即为接收跳转状态的Reducer,代码中我们通过获取StackNavigator的Action来返回最新的处理状态。

2、在rootReducer中注册该reducer:

export default rootReducer = combineReducers({
    Nav
})

3、Store中仍然是注册rootRecuder,使用中间件等等。

4、App首页中绑定(app.js)

@connect(state => ({
    nav: state.nav
}))

class AppWithNavigationState extends Component {
    render() {
        return (
            <Router
                navigation={addNavigationHelpers({
                    dispatch: this.props.dispatch,state: this.props.nav
                })}
            />
        );
    }
}

export default class App extends Component {


    render() {
        return(
            <Provider store={ store }>
                <AppWithNavigationState/>
            </Provider>
               
        )
    }
}
以上代码定义在程序入口中,从代码可以看到,首先使用@connect绑定nav的state,即NavReducer中返回的state。Router就是我们的StackNavigator,对其添加addNavigationHelpers,并将dispatch和state传入。dispatch和nav就是Redux中分发的行为和状态,这样去触发react-navigation的改变。最后使用Provider包含并将store注入到Provider。

总结下流程:

(1)定义navReducer,返回导航状态。(跳转State)

(2)注册reducer。 (将navReducer添加到rootReducer)

(3)创建store。(store中注入rootReducer)

(4)程序入口中将store注入Provider。(Provider将store注入StackNavigator)

(5)@connect获取最新导航状态。(将StackNavigator于=与Redux绑定)

(6)设置StackNavigator的addNavigationHelpers,并将状态和行为传入。(StackNavigator接收到Reducer返回的最新状态,执行相应改变(跳转等))

以上步骤执行完,此时,程序会在@connect抛出错误,因为我们使用了@描述符,所以需要引入如下第三方库:

"babel-plugin-transform-decorators-legacy": "^1.3.4"

(1)npm ibabel-plugin-transform-decorators-legacy --save -dev

(2)项目根目录找到文件,打开添加如下:

{
  "presets": ["react-native"],"plugins":["transform-decorators-legacy"] // 添加引用插件
}
ok,到此通过以上步骤,我们就将Redux和react-navigation整合在一起啦~

老规矩,源码奉上,点击下载

猜你在找的React相关文章