zoukankan      html  css  js  c++  java
  • react native 之 react-redux使用套路

    redux是什么?他是一个state容器,这个容器中存放所有页面的state。

    redux的运作方式是怎样的?

    actions: 可以理解为用户和手机间的交互行为,比如点了一个按钮,下拉刷新,上拉加载更多。。。都可以写成一个action, 一个页面可能会有很多个action。一般action.js中写函数。

    页面因为绑定(订阅)了action 和 state,当用户操作界面时,就会触发action中的函数,action 中的函数拉起reducer,处理数据,然后重新render页面。大概机制就是这样。

    接入方式:

    1. npm install 下列内容:

    npm install --save redux
    npm install --save react-redux
    npm install --save-dev redux-devtools
    
    当项目中用到了导航栏,就需要这样:
    npm install --save react-navigation-redux-helpers
    (大部分App都用到了导航栏, 所以以下是引入了导航栏的情况)

    2. 用<Provider/>包裹根组件, 将store传递给App框架

    这里的根组件就是导航组件,要注意AppNavigator/中除了export default connect()之外,还要导出 export const RootNavigator 和 export const rootCom = 'Init'; 后面在合并reducers要用到这两个

    import React, {Fragment} from 'react';
    import {Provider} from 'react-redux';
    import AppNavigator from '../../navigator/AppNavigator'; //此处AppNavigator并未定义 怎么来的呢? 难道是引入默认导出?
    import store from './store' //还有此处的store


    // import Lamp from './componnets/Lamp' //假如只显示灯一个界面


    const App = () => {

    return <Provider store={store}>
    <AppNavigator/>
    </Provider>
    };

    export default App;

    AppNavigator.js代码

    import { createStackNavigator,
      createAppContainer,
      createBottomTabNavigator,
      createMaterialTopTabNavigator,
      createDrawerNavigator,
      createSwitchNavigator,
     } from 'react-navigation';
    
    import WelcomePage from '../page/WelcomePage';
    import HomePage from '../page/HomePage';
    import DetailPage from '../page/DetailPage';
    
    import MainV from '../calendarPages/Main'
    import NewAct from '../calendarPages/newAct'
    import NewEdit from '../calendarPages/newEdit'
    import ActView from '../calendarPages/actView'//
    import FavoritePage from '../page/FavoritePage';//
    import ModalExamplePage from '../page/ModalExamplePage';
    
    import AnimationPage from '../page/AnimationPage';
    import PanResponderPage from '../page/PanResponderPage';//
    import MyPage from '../page/MyPage';//
    import ComponentLifeCyclePage from '../page/ComponentLifeCyclePage';//
    import JSCallNativePage from '../page/JSCallNativePage';//
    import NativeCallJSPage from '../page/NativeCallJSPage';//
    import ChartPage from '../page/ChartPage';//
    import PromisePage from '../page/PromisePage';//
    import Lamp from '../page/reduxapp/componnets/Lamp';//
    
    import {connect} from 'react-redux';
    import {createReactNavigationReduxMiddleware,createReduxContainer} from 'react-navigation-redux-helpers';
    export const rootCom = 'Init';//设置根路由
    
    import NaviJumpTransParamsPage from '../page/NaviJumpTransParamsPage';
    
    
    const InitNavigator = createStackNavigator({
      WelcomePage:{
        screen:WelcomePage,
        navigationOptions:{
          header:null,
        }
      }
    });
    
    const MainNavigator = createStackNavigator({
      HomePage:{
        screen:HomePage,
        navigationOptions:{
          header:null,
        }
      },
      DetailPage:{
        screen:DetailPage,
        navigationOptions:{
          //header:null,
        }
      },
      MainV:{
        screen:MainV,
        navigationOptions:{
          //header:null,
        }
      },
      NewAct:{
        screen:NewAct,
        navigationOptions:{
          //header:null,
        }
      },
      NewEdit:{
        screen:NewEdit,
        navigationOptions:{
          //header:null,
        }
      },//
      ActView:{
        screen:ActView,
        navigationOptions:{
          //header:null,
        }
      },//
      FavoritePage:{
        screen:FavoritePage,
        navigationOptions:{
          //header:null,
        }
      },
      AnimationPage:{
        screen:AnimationPage,
        navigationOptions:{
          //header:null,
        }
      },
      PanResponderPage:{
        screen:PanResponderPage,
        navigationOptions:{
          //header:null,
        }
      },//
      MyPage:{
        screen:MyPage,
        navigationOptions:{
          title:'',
          //header:null,
        }
      },//
      ComponentLifeCyclePage:{
        screen:ComponentLifeCyclePage,
        navigationOptions:{
          title:'组件的生命周期',
          //header:null,
        }
      },
      JSCallNativePage:{
        screen:JSCallNativePage,
        navigationOptions:{
          title:'',
          //header:null,
        }
      },
      NativeCallJSPage:{
        screen:NativeCallJSPage,
        navigationOptions:{
          title:'',
          //header:null,
        }
      },
      NaviJumpTransParamsPage:{
        screen:NaviJumpTransParamsPage,
      },
      ModalExamplePage:{
        screen:ModalExamplePage,
      },
      ChartPage:{
        screen:ChartPage,
      }
      ,
      PromisePage:{
        screen:PromisePage,
      },
      Lamp:{
        screen:Lamp,
      }
    
    });
    
    //连接InitNavigator和MainNavigator
    
    // const AppNavi = createSwitchNavigator({
    //   Init:InitNavigator,
    //   Main:MainNavigator
    //
    // },{
    //   navigationOptions:{
    //     //header:null,
    //   }
    // });
    // const AppNavigator = createAppContainer(AppNavi);
    // export default AppNavigator;
    
    
    ///////////////////
    
    //连接InitNavigator和MainNavigator
    
    export const RootNavigator = createSwitchNavigator({
      Init:InitNavigator,
      Main:MainNavigator
    
    },{
      navigationOptions:{
        //header:null,
      }
    });
    
    export const middleware = createReactNavigationReduxMiddleware(
    
      state => state.nav,
      'root'
    );
    
    const AppWithNavigationState = createReduxContainer(RootNavigator,'root');
    
    const mapStateToProps = state => ({
      state: state.nav, // v2
    });
    
    export default connect(mapStateToProps)(AppWithNavigationState);
    View Code

    3. 用connect方法, 包裹导航器组件,导出。connect($1,$2)($3) ,其中$1是state 到props 的映射,$2是dispatch 到props的映射, $3是当前组件。

    例如:(这个就是AppNavigator.js代码中最关键的代码)

    export const middleware = createReactNavigationReduxMiddleware(
    
      state => state.nav,
      'root',
    );
    
    const AppWithNavigationState = createReduxContainer(RootNavigator,'root');
    
    const mapStateToProps = state => ({
      state: state.nav, // v2
    });
    
    export default connect(mapStateToProps)(AppWithNavigationState);

    4. 创建store , 利用createStore()函数,传入reducers 作为参数


    import {applyMiddleware,createStore} from 'redux'
    import thunk from 'redux-thunk'
    import reducers from '../reducers';
    import {middleware} from '../../../navigator/AppNavigator'

    // 如何自定义中间件
    const logger = store => next => action => {

    if(typeof action === 'function'){
    console.log('dispatch a function',action);
    }
    else{
    console.log('dispatching',action);
    }
    const result = next(action);
    console.log('nextState',store.getState());

    }

    const middlewares = [
    middleware,
    logger,
    thunk,//暂时没用到
    ];

    export default createStore(reducers,applyMiddleware(...middlewares));

    5. 编写action, 一般action的类型集中定义到一个Types文件中, 一个App的action肯定不止一个两个

    export const SWITCH = 'SWITCH';

    import React, { Component } from 'react';
    export function switchLamp(){

    return dispatch=>{
    dispatch({type:SWITCH})
    }

    }

    6. 编写reducer, 他接收旧的state+action作为参数,然后产生新的state

    例如有一个改变App主题色的redecer写法是这样

    import {SWITCH} from '../../actions/lamp/index';

    const defaultState = {
    light : false
    };

    export default function onAction(state=defaultState,action){

    switch(action.type){
    case SWITCH:
    return {
    light:!state.light,
    };
    default:
    return state;
    }
    }

    7. 在页面中使用,从this.props获取状态容器中的数据, 重新渲染页面。这里原理是只要触发了action, 就会更新state,从而更新界面。

    用了redux , 页面就不直接导出了,而是通过connect函数导出当前组件。

    下面这写代码作用主要是把state绑定到props, 把action绑定到props。这样就能直接在页面用解构赋值取用了。

    
    


    const mapStateToProps = state =>({
    lamp:state.lamp,
    });

    
    

    // 这种写法报错
    // function mapDispatchToProps(dispatch) {
    // return bindActionCreators(actions.switchLamp, dispatch);
    // }

    
    

    const mapDispatchToProps = (dispatch) => {
    return {
    switchLamp: bindActionCreators(actions.switchLamp, dispatch)
    }
    };

    
    

    // const mapDispatchToProps = dispatch => ({
    // switchLamp:() => dispatch(actions.switchLamp),
    //
    // });

    
    

    export default connect(mapStateToProps,mapDispatchToProps)(Lamp);

     

    ----------------------------------------------分割线----------------------------------------------

    后面自己照着做,其间遇到一些小问题,都是步骤不规范引起的。

    比如报错:这个就要检查下reducer中关于导航器的写法了

    TypeError: Cannot read property 'routes' of undefined
    
    This error is located at:
        in Navigator (at create-redux-container.js:92)
        in NavigatorReduxWrapper (created by ConnectFunction)
        in ConnectFunction (at root.js:21)
        in Provider (at root.js:20)
        in App (at renderApplication.js:40)
        in RCTView (at View.js:35)
        in View (at AppContainer.js:98)
        in RCTView (at View.js:35)
        in View (at AppContainer.js:115)
        in AppContainer (at renderApplication.js:39)
    
    getDerivedStateFromProps
        createNavigator.js:1:1972

    应该是这样:

    import {combineReducers} from 'redux'
    import lamp from './lamp'
    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  因为只允许有一个根reducer
    const index = combineReducers({
      nav:navReducer,
      lamp:lamp,
    });
    
    export default index;

    严格按照套路来就可以了,特别要注意下结构目录,不然很难调

    我测试用的demo: https://github.com/nwgdegitHub/Steward_RN

    完整App见: https://github.com/nwgdegitHub/MK_GitHub_App

    参考:https://segmentfault.com/q/1010000012086401/a-1020000012111603

    此文仅为鄙人学习笔记之用,朋友你来了,如有不明白或者建议又或者想给我指点一二,请私信我。liuw_flexi@163.com/QQ群:582039935. 我的gitHub: (学习代码都在gitHub) https://github.com/nwgdegitHub/
  • 相关阅读:
    杭电2074
    关于大整数n!的问题!
    杭电2053
    大整数乘法(高精度)
    JS:获取框架内容
    JQ:hover延迟效果
    jQ+Ajax+PHP 简单实例
    js节省document.getElementById("xxx")的方法
    QQ一键登录功能的实现过程
    点击文字出现文本框
  • 原文地址:https://www.cnblogs.com/liuw-flexi/p/11571959.html
Copyright © 2011-2022 走看看