学过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文件中写个配置文件)

[javascript] view plain copy
  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就是我们应用的最顶层组件)。

[javascript] view plain copy
  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:

[javascript] view plain copy
  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:

[javascript] view plain copy
  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的形式传递给当前页面。)

[javascript] view plain copy
  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

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

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

转载于:https://www.cnblogs.com/summary-2017/p/8626414.html

React Native集成Redux框架讲解与应用相关推荐

  1. React Native 集成分享第三方登录功能分享第三方登录模块开发(iOS)

    期待已久的新课上线啦!解锁React Native开发新姿势,一网打尽React Native最新与最热技术,点我Get!!! 在我们常用的App中经常会看到分享与第三方登录的功能,可以说分享与第三方 ...

  2. React Native集成友盟推送

    React Native集成友盟推送 android推送集成 1.导入SDK: (1)push文件夹位置: (2)将push文件夹直接复制粘贴到rn项目android目录下,目录结构如下: 2.添加修 ...

  3. React Native集成CodePush热更新

    作为一款以JavaScript语音为基础跨平台开发框架,React Native本身已经具备了动态更新的能力,不过官方却没有提供一套标准的动态更新方案.因为一个标准的动态更新方案,除了需要客户端具备动 ...

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

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

  5. React Native 集成极光推送 jpush-react-native

    转载:https://www.jianshu.com/p/a71512a8f921 概述 jpush-react-native 是极光推送官方开发的 React Native 版本插件,可以快速集成推 ...

  6. React Native集成极光推送

    推送作为手机应用的基本功能,是手机应用的重要部分,如果自己实现一套推送系统费时费力,所以大部分的应用都会选择使用第三方的推送服务,如极光推送.下面就以React Native项目集成jpush-rea ...

  7. React Native集成Touch ID和Face ID

    前言: 使用Touch ID也称为指纹身份验证在移动应用程序中非常流行.Touch ID功能可保护应用程序并使其成为用户的无缝身份验证流程. 许多银行应用程序,如美国银行,发现,大通,使用Touch ...

  8. android微信支付插件,React Native集成微信支付【Android】

    wechat.jpg 本次博客主要讲解主要在RN中集成微信支付以及被我踩平的坑,需要一定的原生集成经验! 一. 导入微信SDK 用Android Studio打开RN项目中的android部分,在ap ...

  9. React Native 集成

    mac下为例: 安装:npm install -g react-native-cli 1.新建Podfile文件,并配置需要使用的第三方库 platform:ios, '8.0' target 'Nu ...

最新文章

  1. VS查看C++类的内存分布、初步了解类的内存分布
  2. cf 559a **
  3. 实体类dao接口mysql_利用MyBatis生成器自动生成实体类、DAO接口和Mapping映射文件...
  4. Host Switch Plus结合nginx使用
  5. android studio sift,android - 使用SIFT / SURF通过Android Studio在Android上使用opencv进行特征提取 - 堆栈内存溢出...
  6. Linux系统(Centos)下安装nodejs并配置环境
  7. HANA中SQL之truncate 、delete与drop区别
  8. 上海电信中兴B860A 4K版破解
  9. 判断文件是否为图片格式
  10. 量子卡塔教您如何在Q#中进行量子编程
  11. Docker Jenkins 连接agent:SSH key presented by the remote host does not match the key saved in the Know
  12. 【转自Testerhome】iOS 真机如何安装 WebDriverAgent
  13. 中国AI行业走向:新人胜旧人还是 BAT 牢牢掌握价值链顶端? | 新智元投资领袖论坛...
  14. 怎么把数据文件上传云服务器,如何将数据上传到云服务器上
  15. Android---简易的底部导航栏
  16. 为powerpc编译mtd-utils工具
  17. php openssl函数手册,OpenSSL 函数 - PHP 7 中文文档
  18. 人生观价值观与老生常谈
  19. Oracle根据当前时间获取最近5年,最近6个月,最近30天的时间
  20. 计算机网络信号电平,电平信号什么意思_电平和电压的区别

热门文章

  1. java用链表做学生系统_C语言链表实现学生管理系统
  2. 如何将mysql的数据库渲染到页面_vue.js实现数据库的JSON数据输出渲染到html页面功能示例...
  3. 使用特征_R语言-使用caret包实现特征选择:递归特征消除(RFE)算法
  4. 32位mips运算器logisim_大神教你制作一个简单的16位CPU
  5. vue 断开正在发送的请求_vue 发送请求频繁时取消上一次请求
  6. 给定a和n,计算a+aa+aaa+a...a(n个a)的和(大数据处理)
  7. 浅谈PPM (Project Portfolio Management)
  8. VUE: 当前页面 引用自定义公用样式 (:style=“样式名“)
  9. Docker 实战:编写 Dockerfile
  10. Docker : 数据卷(创建、挂载、查看、删除)