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/
原文地址:https://www.cnblogs.com/liuw-flexi/p/11571959.html