• React-Navigation与Redux整合详解


    本文转自:文章地址:http://blog.csdn.net/u013718120/article/details/72357698

    继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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    export let main = (url, params, isLoading, isLoadMore, isRefreshing) => {
        return dispatch => {
     
            // 1.发出拉取数据的信号
            dispatch(loadMainContent(isLoading, isLoadMore, isRefreshing));
     
            // 2.请求网络
            return HttpUtil.fetchGet(url, params,
                (responseObj) => {
                    dispatch(receiveMainContent(responseObj.result.bookList));
                    console.info("success");
                },
                (error) => {
                    dispatch(receiveMainContent([]));
                    console.info("error" + error);
                }
            )
        }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    let loadMainContent = (isLoading, isLoadMore, 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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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({}, state, {
                    isLoading: false,
                    isRefreshing: false,
                    mainList: state.isLoadMore ? state.mainList.concat(action.mainList) : action.mainList
                })
            default:
                return state;
        }
    }

    上面代码定义了对应的Reducer,用来接收Action的行为,并进行处理,最终返回最新状态State。

    3、整合Reducer

    1
    2
    3
    4
    export default rootReducer = combineReducers({
        Main,
     
    })

    4、Store

    1
    2
    3
    4
    let store = createStore(rootReducer, {}, compose(
      applyMiddleware(thunk),
      window.devToolsExtension ? window.devToolsExtension() : f => f
    ))

    Store相对简单,因为Redux本身没有异步概念,不能直接使用setTimeOut等,但是网络处理需要异步进行,并且结果是异步返回,所以为了处理此种情况,可以使用中间件react-thunk帮助我们完成。

    5、Connect

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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其实就充当了程序的入口,负责视图界面之间的跳转交互。

    1
    2
    3
    4
    5
    const AppNavigator = StackNavigator(
        {
            Splash: { screen: SplashScene },
        }

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    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:

    1
    2
    3
    export default rootReducer = combineReducers({
        Nav
    })

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    @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抛出错误,因为我们使用了@描述符,所以需要引入如下第三方库:

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

    (1)npm i babel-plugin-transform-decorators-legacy --save -dev

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

    1
    2
    3
    4
    {
      "presets": ["react-native"],
      "plugins":["transform-decorators-legacy"] // 添加引用插件
    }

    ok,到此通过以上步骤,我们就将Redux和react-navigation整合在一起啦~

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

    刚创建的React Native交流11群:112490774,欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!

    尊重原创,转载请注明:From Sky丶清(http://www.lcode.org) 侵权必究!

    引用原文:http://www.lcode.org/react-navigation-redux/

    写博客是为了记住自己容易忘记的东西,另外也是对自己工作的总结,文章可以转载,无需版权。希望尽自己的努力,做到更好,大家一起努力进步!

    如果有什么问题,欢迎大家一起探讨,代码如有问题,欢迎各位大神指正!

  • 相关阅读:
    idea 设置注释
    SVN解决冲突
    mysql执行 sql文件遇到USING BTREE ) ENGINE=MyISAM DEFAULT CHARSET=utf8错误
    如何查看JDK以及JAVA框架的源码
    一道常被人轻视的前端JS面试题
    Js 常用调试的方法
    主要的Ajax框架都有什么?
    Ajax使用的五步法
    Java正则表达式
    查出在当天所处的日期区间的某些数据
  • 原文地址:https://www.cnblogs.com/summary-2017/p/8626361.html
Copyright © 2020-2023  润新知