1.Redux的基本用法

前言

说明: 本文只针对移动端的Redux的基本用法进行描述。

  1. 希望这一篇文章,就能帮助你搞定redux的基本用法,甚至不用再去查阅其他文档。
  2. 因为我个人脑子比较笨,查阅了很多文档,看了不少视频资料才理解了。

2. 原理阐述(个人根据对官方文档理解的阐述)

  1. 关键词 store、action、reducer
  2. store是全局唯一的(在服务端可能有多个,但是我们在移动开发中,只有一个),它的作用是用来存储数据。
  3. action,翻译过来就是“动作,行动”的意思。 在我们这里,我们可以理解为对一种行动的描述,包括名字,要做的事情,参数等。
  4. reducer,翻译过来就是“减速器”的意思,个人理解为缓冲者可能比较妥当。
    (1)意思是,当有人发送一个action,会给到reducer来处理,或者作为一个缓冲地带,来进行一些数据处理。
    (2)处理后的数据会存储到store中,而且这是唯一可以改变store中的数据方法。
  5. 数据的使用
    (1)get方法,在UI界面中,数据源通过get方法获取
    (2)set方法,在这里没有直接的set方法,要修改数据,通过dispatch来set (dispatch翻译过来就是发送,派遣,邮寄的意思,我们可以理解为发送快递的方式)
    (3)这里通过dispatch发送的包裹,就是action(这里有一些我们想修改的数据相关内容)
  • 数据流向图(单一数据流向)

3.脑海里大概有个上面的数据流向图即可,先看下面的代码(最好自己也写一遍,会加深印象,有助于理解)

  • 文件目录结构如下

一. 我们先搭建一个简单的界面(View1–index.js)

import React, { Component } from 'react';
import {Button,Text,View,StyleSheet
} from 'react-native';import { connect } from 'react-redux';
import * as uiAction from '../Redux/action/uiActions';class Home extends Component {constructor(props) {super(props);this.state = {name: "张三",age: 18}}render() {return (<View style = {styles.container}><Text>Hello, my name is { this.state.name },I'm {this.state.age} years old</Text><Button title='增加年龄'onPress={() => {}}/><Button title='减少年龄'onPress={() => {}}/><Button title='修改姓名'onPress={() => {}}/></View>)}
}export default Homeconst styles = StyleSheet.create({container: {justifyContent: 'center',alignItems: 'center',flex: 1}
})

二. 我们想做的事情很简单

  1. 点击增加或减少年龄,修改界面的年龄显示
  2. 点击修改名字,修改界面的名字显示
  • 那么我们如何通过Redux来实现呢?我们分为几个步骤。

三.Redux的使用步骤(本文核心内容)

开始之前,我们导入依赖库

一次性导入依赖库:
yarn add immutable \
react-redux \
redux \
redux-logger \
redux-promise-middleware \
redux-thunk

1.step one
  • 创建action、reducer、store
    (1) 我们创建actionType.js文件
import { ActionType } from 'redux-promise-middleware';/*
* 编程规范建议:
* 1. 我们的每个action大类,个人觉得以ActionXX来开头命名,
*    使用的时候更能体现见名知意。
* 2. 里面对具体某个action,个人觉得以K开头,更能区分代表是具体action的key值
*/
export const actionType = {ActionUI: {  KaddAge:                 "addAge",KdecrementAge:           "decrementAge",KmodifyName:             "modifyName"}
}

(2) 我们创建uiActions.js文件

import { actionType } from "./actionType";/*** 通常,根据action类型来命名函数*//*
* type:表示是action的具体类型,我们可以直接使用我们上个actionType
* payload: 表示参数,也是外面传过来的参数
* 在这里,addAge函数,就是dispatch发送的包裹了
*/
export function addAge(age) {return {type: actionType.ActionUI.KaddAge,payload: age}
}export function decrementAge(age) {return {type: actionType.ActionUI.KdecrementAge,payload: age}
}export function modifyName(name) {return {type: actionType.ActionUI.KmodifyName,payload: name}
}

(3) 创建所有action的入口函数,index.js,我们这里暂时没有创建

export * from './uiAction'
export * from './xxAction'  // 如果有别的action,可以统一放到这里
export * from './xxxAction'
2.step two

(1)创建uiReducer.js文件

import { actionType } from "../action/actionType";
import { fromJS } from "immutable";/*** 初始状态,不可变的,这里的state的的key,都是在UI界面中的state可以直接调用的* 比如:界面一个文本的名字内容,显示什么,就是直接用这里的myName*/function initialState() {return fromJS({myName: "张三",myAge: 18});}/**
* 这里为了代码的简洁性、可读性、维护性、解耦性
* 我们不要写成switch语句,否则一个函数的行数很容易超过50行
* 个人不建议一个函数的行数超过50行
*
*  我们这里根据prototype来定义多个函数,只是参数的类型不同
*  有点像C++里的函数重载
*/
export default function reducer(state = initialState(), action) {if (typeof reducer.prototype[action.type] === 'function') {return reducer.prototype[action.type](state, action);} else {return state;}
}reducer.prototype[actionType.ActionUI.KaddAge] = (state, action) => {return state.set('myAge', action.payload);
}reducer.prototype[actionType.ActionUI.KdecrementAge] = (state, action) => {return state.set('myAge', action.payload);
}reducer.prototype[actionType.ActionUI.KmodifyName] = (state, action) => {return state.set('myName', action.payload);
}

(2)创建reducer的入口函数,index.js

import ui from './uiReducer';
import otherReducer from './otherReducer'; // 假如还有其他reducer
import { combineReducers } from 'redux';export default combineReducers({ui,otherReducer // 如果还有其他reducer,就这样类似往里面添加
});
3.step three

创建store,也是唯一的store

import { applyMiddleware, createStore } from "redux";
import { createLogger } from "redux-logger";
import thunk from "redux-thunk";
import promise from "redux-promise-middleware";
import reducer from '../reducer';// 分为调试环境 和 release环境,调试环境就有log日志
const middleware = __DEV__ ?applyMiddleware(promise, thunk, createLogger()):applyMiddleware(promise, thunk)export default createStore(reducer, middleware)
  • 到此为止,我们已经完成了80%了。如果能看到这里,提前恭喜一下你!
4.step four
  • 现在需要把redux和UI界面串联起来
  • 对于下面的没有使用过redux的UI界面,我们开始改造
class Home extends Component {constructor(props) {super(props);this.state = {name: "张三",age: 18}}render() {return (<View style = {styles.container}>{...}</View>)}
}
export default Home

(1)去掉constructor
(2)导入connect,导入把export default Home改为:

import { connect } from 'react-redux';export default connect((state) => {return {person: state.ui};})(Home);

(3) 用Provider包裹整个APP

import React from 'react';
import { Provider } from 'react-redux';
import store from './smallDemo/Redux/store/store';const ReduxApp = () => (<Provider store={store}><App /></Provider>
)AppRegistry.registerComponent(appName, () => ReduxApp);

(4) dispatch的使用方法

   render() {return (<View style = {styles.container}><Text>Hello, my name is { this.props.person.get('myName') },I'm {this.props.person.get('myAge')} years old</Text><Button title='增加年龄'onPress={() => {this.props.dispatch(uiAction.addAge(this.props.person.get('myAge') + 20))}}/><Button title='减少年龄'onPress={() => {this.props.dispatch(uiAction.addAge(this.props.person.get('myAge') - 10))}}/><Button title='修改姓名'onPress={() => {this.props.dispatch(uiAction.modifyName("zhangsan"))}}/></View>)}
  • 到此为止,我们已经阐述完了整个redux的基本使用方法
  • end~ Thanks!

RN开发系列<8>--Redux(1)入门篇相关推荐

  1. RK3399平台开发系列讲解(内核入门篇)1.2、如何高效的阅读Linux内核设备驱动

    文章目录 如何高效阅读内核代码 一.找驱动切入点(山有小口,仿佛若有光) 1.1 设备驱动入口 1.2 子系统入口 1.3 那么内核本身的入口又在哪里呢? 二.理清主脉络(会当凌绝顶,一览众山小) 三 ...

  2. RK3399平台开发系列讲解(内核入门篇)1.1、通过sysfs清楚了解设备的系统状况

    =>返回专栏总目录<= 文章目录 1.不敢高声语,恐惊天上人:sysfs目的 2.窥一斑而知全豹:sysfs目录介绍 3.千丝万缕:sysfs中要素的关系 4.数据观星:sysfs中相关结 ...

  3. RK3399平台开发系列讲解(内核入门篇)1.46、RTC驱动开发

    平台 内核版本 安卓版本 RK3399 Linux4.4 Android7.1

  4. RK3399平台开发系列讲解(内核入门篇)1.18、 Sysfs设备驱动管理

  5. RK3399平台开发系列讲解(内核入门篇)1.42、Linux 文件系统是怎么工作的?

    平台 内核版本 安卓版本 RK3399 Linux4.4 Android7.1

  6. RK3399平台开发系列讲解(内核入门篇)1.53、platform平台设备

  7. RK3399平台开发系列讲解(内核入门篇)1.48、LDM数据结构详解

  8. RK3399平台开发系列讲解(内核入门篇)1.3、从内核的角度看外设芯片的驱动

    =>返回专栏总目录<= 文章目录 一.芯片的基本功能模块 1.1.复位 1.2.中断 1.3.接口 2.一个完整的芯片驱动 2.1.初始化 2.2.芯片的正常工作状态 2.3.suspen ...

  9. openlayers入门开发系列之地图属性查询篇

    本篇的重点内容是利用openlayers实现地图属性查询功能,效果图如下: 实现思路: 模糊查询点击事件 //模糊查询 $("#swatchQuery").bind("c ...

  10. 【微信小程序开发•系列文章一】入门

    本系统文章主要有以下几篇: <[微信小程序开发•系列文章一]入门> <[微信小程序开发•系列文章二]视图层> <[微信小程序开发•系列文章三]数据层> <[微 ...

最新文章

  1. Java String,StringBuilder和StringBuffer的区别 StringBuilder StringBuffer String
  2. Java设计模式-中介者模式
  3. centos7 下通过nginx+uwsgi部署django应用
  4. C++总结笔记(七)—— 运算符重载
  5. 多台电脑集群运算_一个分布式服务器集群架构方案
  6. nginx 优化,突破十万并发
  7. maven自定义本地仓库目录
  8. 永久免费http升级到https
  9. Java中使用KCP协议
  10. python机器学习案例系列教程——文档分类器,朴素贝叶斯分类器,费舍尔分类器
  11. 同济大学 线性代数 第六版 pdf_【课后习题答案】工程数学线性代数同济第六版+课后习题答案...
  12. 2021华为软挑赛题_思路分析——实时更新,做多少更多少(二)
  13. Android M 设置里面关于手机型号的修改
  14. 压缩软件如何删除压缩包密码(zip、rar、7-zip),忘记密码如何删除密码?
  15. 微信支付及支付宝支付开发指南
  16. 托业考试 与 托福考试
  17. Android权限 - 权限分类
  18. 周末作业-循环练习题
  19. antd DatePicker 组件 月份和星期显示英文
  20. ZigBee的无线通信与网络组建

热门文章

  1. 安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错”(错误原因、详细分析及解决方法)以及在Windows Server2012上安装.NET Framework 3
  2. android跑马灯源码,Android跑马灯的简单实现方式
  3. 【读书笔记】深入浅出数据分析
  4. SSH学习之一 OpenSSH基本使用
  5. c语言程序设计二级考试哪些题型,计算机二级考试题型
  6. java-高级编程课-实验题集标答整理
  7. 私塾 java_JAVA私塾
  8. informix数据库unload下载数据和load上传数据
  9. 该更新一下你的密码字典了
  10. 安装2000服务器显示文件挂起,MS sql server 2000安装中的提示挂起的解决方案。