react native 之 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);
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
react native 之 redux 使用套路的更多相关文章
- [RN] React Native 使用 Redux 比较详细和深刻的教程
React Native 使用 Redux 比较详细和深刻的教程 React Native 使用 Redux https://www.jianshu.com/p/06fc18cef56a http:/ ...
- React Native——我的学习套路
学习东西都有一定的套路,特别是新的框架,对于React Native,我是这么学的. 第一步 : 这是啥 在各种原因下,需要使用某个框架时,那第一件事就是知道这个框架是用来干什么.React Nati ...
- React Native集成Redux框架讲解与应用
学过React Native的都知道,RN的UI是根据相应组件的state进行render的,而页面又是由大大小小的组件构成,导致每个组件都必须维护自身的一套状态,因此当页面复杂化的时候,管理stat ...
- react native 之 redux
第一章 认识redux 说的通俗且直白一点呢,就是redux提供了一个store,独立的一个内存区,然后放了一些state,你可以在任何component中访问到state,这些state要更改怎么 ...
- React Native使用Redux总结
1>npm安装redux: "react-redux": "^5.0.5", "redux": "^3.7.1", ...
- [转] 学习React Native必看的几个开源项目
http://www.lcode.org/study-react-native-opensource-one/ http://gold.xitu.io/entry/575f498c128fe10057 ...
- 学习React Native必看的几个开源项目
学习React native ,分享几个不错的开源项目,相信你学完之后,一定会有所收获.如果还没有了解RN的同学们可以参考手把手教你React Native 实战之开山篇<一> 1.Fac ...
- 从React Native到微服务,落地一个全栈解决方案
Poplar是一个社交主题的内容社区,但自身并不做社区,旨在提供可快速二次开发的开源基础套件.前端基于React Native与Redux构建,后端由Spring Boot.Dubbo.Zookeep ...
- react native redux saga增加日志功能
redux-logger地址:https://github.com/evgenyrodionov/redux-logger 目前Reac native项目中已经使用redux功能,异步中间件使用red ...
随机推荐
- android gradle项目剖析
1 配置文件 1.1 gradle属性文件 1.1.1 gradle.properties 对项目范围内的gradle进行配置,比如设置cache. 1.1.2 local.properties 设置 ...
- 【转】centos7安装
转自:https://blog.csdn.net/qq_42570879/article/details/82853708 1.CentOS下载CentOS是免费版,推荐在官网上直接下载,网址:htt ...
- [多校联考2019(Round 5 T2)]蓝精灵的请求(二分图染色+背包)
[多校联考2019(Round 5)]蓝精灵的请求(二分图染色+背包) 题面 在山的那边海的那边住着 n 个蓝精灵,这 n 个蓝精灵之间有 m 对好友关系,现在蓝精灵们想要玩一个团队竞技游戏,需要分为 ...
- Python虚拟环境命令
cd D:\virtual\ virtualenv -p D\Python35\python.exe env1 cd env1 cd Scripts activate.bat # 激活该虚拟环境 de ...
- asp.net后台cs中的JSON格式变量在前台Js中调用方法
//后台cs代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...
- ThinkPHP关联模型如何关联非主键
ThinkPHP关联模型默认是主键外键关联 官方并没有提供相关文档 如何实现非主键与非主键间之间的关联 <?php namespace Admin\Model; use Think\Model\ ...
- php-redis的配置与使用
从此处下载 https://codeload.github.com/phpredis/phpredis/zip/develop 也就php-redis的安装包,在zip格式,在windows下解压,将 ...
- 关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑
JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反 ...
- iOS之Run Loop详解
转自标哥的技术博客(www.henishuo.com) 前言 做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一 ...
- Centos安装 Apache2.4提示 APR not found的解决办法
在安装apache2.2.22版本的时候没有任何问题,可直接使用命令编译安装. 但是,在apache 2.4.12版本,./configure 进行配置时, 提示 configure: error: ...