学过React Native的都知道,RN的UI是根据相应组件的state进行render的,而页面又是由大大小小的组件构成,导致每个组件都必须维护自身的一套状态,因此当页面复杂化的时候,管理state会相当吃力的。而redux提供了一套机制来组织管理整个应用状态。

Redux有三部分组成:store,action,reducer。

store:维护全局的state,以及将action和reducer结合起来。

action:用来传递state的信息。(比如:我们在action中处理登陆操作,将返回的user对象传递给对应的reducer.)

reducer:reducer是简单的处理函数,通过传入旧的state和指示操作的action来更新state,从而达到页面的刷新。

下面通过一个简单的例子来集成下。

首先安装相关库:

安装redux:npm install --save redux

安装redux绑定库:npm install --save react-redux

安装开发者工具:npm install --save-dev redux-devtools

安装异步action构造器:npm install --save redux-thunk

在集成之前熟悉下一般基于Redux的目录结构:


.
├── src #开发目录
| |
| ├──constants #ActionTypes和Urls
| |
| ├──actions #actions的文件
| |
| ├──components #内部组件
| |
| ├──containers #容器组件
| |
| ├──reducers #reducer文件
| |
| ├──stores #store配置文件
| |
| └──utils #工具
|
├── node_modules #包文件夹
├── .gitignore
├── index.js #入口文件
└── package.json

(如果你之前不了解Redux的话,或许会比较蒙圈,但不要紧,跟着流程多走几遍,试着推敲先分析下流程,慢慢就理解了)

/*************************************store*************************************/

1.首先创建全局的store。(一般在stores文件中写个配置文件)

  1. 'use strict';
  2. import { createStore, applyMiddleware ,combineReducers} from 'redux';
  3. import thunk from 'redux-thunk';//引入异步操作
  4. //引入所有的reducers,切记要在index.js封装下.
  5. import * as reducers from '../reducers';
  6. const middlewares = [thunk];
  7. const createSoreWithMiddleware=applyMiddleware(...middlewares)(createStore);
  8. //配置store信息
  9. export default function configureStore(initialState){
  10. //将reducer组合起来
  11. const reducer=combineReducers(reducers);
  12. //创建store
  13. const store=createSoreWithMiddleware(reducer,initialState);
  14. return store;
  15. }

简单讲解下:

首先引入该APP中所有的reducer,根据上面的目录结构,我们把所有的reducer放入到reducers文件中,切记要加入个index.js进行配置.上面很多都是固定格式,暂时先不分析为什么,做的目的就是返回一个全局的store.

store的应用(这里的APP就是我们应用的最顶层组件)。

  1. import React, { Component } from 'react';
  2. import {Provider} from 'react-redux';
  3. import App from './containers/app';
  4. import configureStore from './store/configureStore';
  5. const store=configureStore();//获取store
  6. export default class Root extends Component{
  7. render(){
  8. return(
  9. <Provider store={store}>
  10. <App/>
  11. </Provider>
  12. );
  13. }
  14. }

App组件其实可以把所有的页面加入到这里,全局进行控制(官方F8是这么操作的)。不过这里暂时先不这样处理,关于navigator的push,pop操作还是放到对应的页面进行处理,更符合我们的原生开发逻辑。

简单看下store中结构:

/*************************************action*************************************/

创建登陆对应的action:

  1. import * as types from './types';
  2. import {Alert}from 'react-native';
  3. //登陆(登陆操作属于耗时操作,所以需要异步执行,这里采用dispatch分发)
  4. export function login(user){
  5. return dispatch=>{
  6. //登陆中,派遣给LOGIN_ING
  7. dispatch({type:types.LOGIN_ING});
  8. let result=fetch('http://www.baidu.com')
  9. .then((res)=>{
  10. //延时2s为了模拟效果
  11. setTimeout(()=>{
  12. if(user.phone=='15221850400'&&user.password=='123456'){
  13. dispatch({type:types.LOGIN,user:user});
  14. }else{
  15. //这里分发的是action
  16. Alert.alert('用户名或密码错误');
  17. dispatch(error());
  18. }
  19. },1000);
  20. }).catch((err)=>{
  21. alert(err);
  22. dispatch({type:types.LOGIN_ERROR});
  23. })
  24. }
  25. }
  26. function error(){
  27. return {
  28. type:types.LOGIN_ERROR
  29. };
  30. }
  31. //登出(由于登出操作一般都只是清空一些数据,不需要异步执行直接返回就可以了,)
  32. export function logout(){
  33. return {
  34. type:types.LOGOUT,
  35. };
  36. }

逻辑还算简单,就只是做个用户名,密码判断,但或许会问dispatch是个什么玩意,哪来的呢,其实上面我们也截图出来了,这个方法是我们创建全局store中的方法。

至于action正常的应该只是一个含有type的json对象,但是为了扩展性,一般会写成函数的形式,俗称action creator如上面的logout方法.

至于login方法由于需要网络操作,固然是异步的,就好比我们原生开发的时候请求API的操作一般都会丢到一个线程中,通过Handler消息机制来渲染UI.

dispatch({type:types.LOGIN_ING}):根据相应的action来进行调用对应reducer方法。

/*************************************reducer*************************************/

接着我们看下最后一个reducer:

  1. import * as types from '../actions/types';
  2. const initialState={
  3. isLoggedIn:false,//登陆状态
  4. user:{},
  5. status: null,//登陆操作状态 ‘done’:已登陆,'doing':正在登陆,null:没有登陆
  6. };
  7. //reducer处理函数更新state,渲染UI(主要根据传入旧的state,)
  8. export default function user(state=initialState,action={}){
  9. switch(action.type) {
  10. case types.LOGIN:
  11. return{
  12. ...state,
  13. isLoggedIn:true,
  14. user:action.user,
  15. status: 'done',
  16. }
  17. break;
  18. case types.LOGIN_ING:
  19. return {
  20. ...state,
  21. isLoggedIn:false,
  22. status: 'doing',
  23. }
  24. break;
  25. case types.LOGIN_ERROR:
  26. console.log('types.LOGIN_ERROR...');
  27. return{
  28. ...state,
  29. isLoggedIn: false,
  30. status: null,
  31. };
  32. break;
  33. case types.LOGOUT:
  34. return {
  35. ...state,
  36. isLoggedIn:false,
  37. status:null,
  38. }
  39. break;
  40. //切莫忘记default返回值
  41. default:
  42. return state;
  43. }
  44. }

reducer其实就是根据一系列action的处理函数,好比我们在前面action中返回的有LOGIN,LOGIN_ING,LOGIN_ERROR等状态,然后调用reducer根据不同的type返回当前最新的state,然后再render ui。

/*************************************connect*************************************/

redux的三部分至此就操作完毕,但如果进行链接起来呢,这里就用到connect组件,connect是将某一个组件(这里一般指一个页面)和store链接起来,目的就是获取当前页面所需的state以及dispatch方法。(从全局state中获取这个页面需要的数据然后以props的形式传递给当前页面。)

  1. import React, { Component } from 'react';
  2. import {
  3. StyleSheet,
  4. TextInput,
  5. Text,
  6. View,
  7. TouchableHighlight,
  8. ActivityIndicator,
  9. } from 'react-native';
  10. import {connect} from 'react-redux';//将我们的页面和action链接起来
  11. import {bindActionCreators} from 'redux';//将要绑定的actions和dispatch绑定到一起
  12. import * as actionCreators from '../actions/loginActions';//导入需要绑定的actions
  13. import Modal from 'react-native-modalbox';
  14. import Home from './home';
  15. /**
  16. 登陆页面
  17. **/
  18. class Login extends Component{
  19. constructor(props){
  20. super(props);
  21. this.state={
  22. }
  23. this.login=this.login.bind(this);
  24. this.onChangePhone=this.onChangePhone.bind(this);
  25. this.onChangePswd=this.onChangePswd.bind(this);
  26. }
  27. onChangePhone(text){
  28. this.setState({'phone':text,});
  29. }
  30. onChangePswd(text){
  31. this.setState({'password':text,});
  32. }
  33. login(){
  34. if(!this.state.phone||!this.state.password){
  35. alert('用户名或密码不能为空!');
  36. }else{
  37. this.refs.modal.open();//loading 状态
  38. this.props.actions.login({'phone':this.state.phone,'password':this.state.password});//dispath 登陆
  39. }
  40. }
  41. //该方法首次不会执行,如果返回false,则reduer不会执行,,
  42. shouldComponentUpdate(nextProps,nextState){
  43. const {isLoggedIn,navigator}=nextProps;
  44. if(isLoggedIn){
  45. this.setState({phone:'',password:''});
  46. navigator.push({
  47. component:Home,
  48. name:'Home',
  49. });
  50. }
  51. return true;
  52. }
  53. render(){
  54. console.log('render...');
  55. return(
  56. <View style={{flex:1}}>
  57. <View style={{padding:20,marginTop:50}}>
  58. <View style={styles.item}><Text style={{width:70}}>手机号码</Text>
  59. <TextInput
  60. style={styles.input}
  61. onChangeText={this.onChangePhone}
  62. placeholder='请输入手机号码'
  63. value={this.state.phone}
  64. />
  65. </View>
  66. <View style={styles.item}>
  67. <Text style={{width:70}}>密码</Text>
  68. <TextInput
  69. style={styles.input}
  70. onChangeText={this.onChangePswd}
  71. placeholder='请输入密码'
  72. password={true}
  73. value={this.state.password}
  74. />
  75. </View>
  76. <TouchableHighlight style={styles.button}
  77. underlayColor='#000000' onPress={this.login}>
  78. <Text style={{fontSize:16,color:'#fff'}}>登陆</Text>
  79. </TouchableHighlight>
  80. </View>
  81. <Modal
  82. style={styles.modal}
  83. ref='modal'
  84. isOpen={this.props.status=='doing'?true:false}
  85. animationDuration={0}
  86. position={"center"}
  87. >
  88. <ActivityIndicator
  89. size='large'
  90. />
  91. <Text style={{marginTop:15,fontSize:16,color:'#444444'}}>登陆中...</Text>
  92. </Modal>
  93. </View>
  94. );
  95. }
  96. }
  97. const styles =StyleSheet.create({
  98. item:{
  99. flex:1,
  100. flexDirection:'row',
  101. alignItems:'center',
  102. height:50,
  103. borderBottomColor:'#ddd',
  104. borderBottomWidth:1,
  105. },
  106. input:{
  107. flex:1,
  108. fontSize:14,
  109. },
  110. button:{
  111. backgroundColor:'#1a191f',
  112. height:50,
  113. marginTop:40,
  114. justifyContent:'center',
  115. alignItems:'center'
  116. },
  117. modal: {
  118. justifyContent: 'center',
  119. alignItems: 'center',
  120. width:150,
  121. height:150,
  122. borderRadius:10,
  123. },
  124. });
  125. //根据全局state返回当前页面所需要的信息,(注意以props的形式传递给Login)
  126. function mapStateToProps(state){
  127. return{
  128. isLoggedIn:state.user.isLoggedIn,
  129. status:state.user.status,
  130. };
  131. }
  132. //返回可以操作store.state的actions,(其实就是我们可以通过actions来调用我们绑定好的一系列方法)
  133. function mapDispatchToProps(dispatch){
  134. return {
  135. actions: bindActionCreators(actionCreators, dispatch)
  136. };
  137. }
  138. //链接起来
  139. export default connect(mapStateToProps,mapDispatchToProps)(Login);

上面的代码不用仔细看,主要是尾部的部分,

mapStateToProps方法:根据全局state返回当前页面所需的数据然后以props的形式传递给当前页面(Login)。

mapDispatchToProps:该方法就是将dispatch和当前页面引入的actionCreators绑定在一起,然后就可以轻松调用。

如:login方法中的:

this.props.actions.login({'phone':this.state.phone,'password':this.state.password});//dispath 登陆

这样整体集成就完毕了,这里简单总结下:

1.首先我们创建全局的store(基于所有的reducer)在APP最外层引用,然后我们创建action(可以根据页面或者某种类别来定义)。接着我们创建reducer(可以设计成跟action一一对应)。最后通过connect将它们和页面链接起来,至于action和reducer的内容,可以等页面编辑OK后再进行设计。

2.执行简单流程:在页面中首先调用对应action方法(传递参数)--->执行相应的业务逻辑,然后调用dispatch(action)(将结果以action的形式传递给reducer)--->在reducer中根据type字段然后返回最新的state,然后在进行render具体的ui。

引用原文:https://blog.csdn.net/jj120522/article/details/52071469

可以参考:https://www.jianshu.com/p/4139babc6d5e

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

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

React Native集成Redux框架讲解与应用的更多相关文章

  1. Angular团队公布路线图,并演示怎样与React Native集成

    本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2015/06/angular-2-react-native-roadmap 前不久在旧 ...

  2. 将React Native集成至Android原生应用

    将React Native集成至Android原生应用 Android Studio 2.1 Preview 4生成的空项目 react-native 环境 0.22.2 初次编译后apk有1.1M, ...

  3. [RN] React Native 使用 Redux 比较详细和深刻的教程

    React Native 使用 Redux 比较详细和深刻的教程 React Native 使用 Redux https://www.jianshu.com/p/06fc18cef56a http:/ ...

  4. 一次掌握 React 与 React Native 两个框架

    此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React 与 React Native 结合学习的方法. 1. 软件开发语言与框架的学习本质 我 ...

  5. 将React Native 集成进现有OC项目中(过程记录) 、jsCodeLocation 生成方式总结

    将RN集成到现有OC项目应该是最常见的,特别是已经有OC项目的,不太可能会去专门搞个纯RN的项目.又因为RN不同版本,引用的依赖可能不尽相同,所以特别说明下,本文参考的文档是React Native ...

  6. react native 之 redux 使用套路

    redux是什么?他是一个state容器 redux的运作方式是怎样的? 接入方式: 1. npm install 下列内容: npm install --save redux npm install ...

  7. react native 之 redux

    第一章  认识redux 说的通俗且直白一点呢,就是redux提供了一个store,独立的一个内存区,然后放了一些state,你可以在任何component中访问到state,这些state要更改怎么 ...

  8. react native 集成react navigation报错

    集成后出现:“Invalid escape sequence at line 1 column 29 path $[0].name”的错误. 解决办法:

  9. React Native使用Redux总结

    1>npm安装redux: "react-redux": "^5.0.5", "redux": "^3.7.1", ...

随机推荐

  1. Jmeter_远程启动 I

    Jmeter 是Java 应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起JAVA内存溢出错误. 其实,Jmeter的 ...

  2. 编写高质量代码--改善python程序的建议(三)

    原文发表在我的博客主页,转载请注明出处! 建议十三:警惕eval()的安全漏洞 相信经常处理文本数据的同学对eval()一定是欲罢不能,他的使用非常简单: eval("1+1==2" ...

  3. ThinkPHP中通过URL重写隐藏应用的入口文件index.php的相关服务器的配置

    [ Apache ] 将httpd.conf配置文件中mod_rewrite.so所在行前面的‘#’去掉 AllowOverride None 将None改为 All 效果图

  4. Golang Frameworks

    Web frameworks help developers build applications as easily and quickly as possible. Go is still rel ...

  5. SQL-修改: 将日期修改为空NULL、修改为空的记录

    1.将日期修改为空NULL update 表 set 字段=null where 字段='' 如果设置为‘’,会默认1900-01-01 2.修改为空的记录 update [dbo].[pub_ite ...

  6. 巨蟒python全栈开发flask5

    1.轮询&&长轮询&&长连接 2.GeventWebsocket 3.Websocket群聊 4.Websocket单聊 5.websocket握手 6.websock ...

  7. Group By 与 Count

    select UserID,COUNT(0) From [Order] a Group By UserID UserID   (无列名)1             5     2            ...

  8. 翻页bug 在接口文档中应规范参数的取值区间

    <?php$a=array("red","green","blue","yellow","brown&q ...

  9. IO流入门-第一章-FileInputStream

    FileInputStreamj基本用法和方法示例 import java.io.*; public class FileInputStreamTest01 { public static void ...

  10. 第04章—整合Mybatis

    spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html 码云源码地址:https://gitee.com/jinxia ...