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/
  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/liuw-flexi/p/11571959.html
Copyright © 2011-2022 走看看