RN开发系列<8>--Redux(1)入门篇
1.Redux的基本用法
前言
说明: 本文只针对移动端的Redux的基本用法进行描述。
- 希望这一篇文章,就能帮助你搞定redux的基本用法,甚至不用再去查阅其他文档。
- 因为我个人脑子比较笨,查阅了很多文档,看了不少视频资料才理解了。
2. 原理阐述(个人根据对官方文档理解的阐述)
- 关键词 store、action、reducer
- store是全局唯一的(在服务端可能有多个,但是我们在移动开发中,只有一个),它的作用是用来存储数据。
- action,翻译过来就是“动作,行动”的意思。 在我们这里,我们可以理解为对一种行动的描述,包括名字,要做的事情,参数等。
- reducer,翻译过来就是“减速器”的意思,个人理解为缓冲者可能比较妥当。
(1)意思是,当有人发送一个action,会给到reducer来处理,或者作为一个缓冲地带,来进行一些数据处理。
(2)处理后的数据会存储到store中,而且这是唯一可以改变store中的数据方法。 - 数据的使用
(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}
})
二. 我们想做的事情很简单
- 点击增加或减少年龄,修改界面的年龄显示
- 点击修改名字,修改界面的名字显示
- 那么我们如何通过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)入门篇相关推荐
- RK3399平台开发系列讲解(内核入门篇)1.2、如何高效的阅读Linux内核设备驱动
文章目录 如何高效阅读内核代码 一.找驱动切入点(山有小口,仿佛若有光) 1.1 设备驱动入口 1.2 子系统入口 1.3 那么内核本身的入口又在哪里呢? 二.理清主脉络(会当凌绝顶,一览众山小) 三 ...
- RK3399平台开发系列讲解(内核入门篇)1.1、通过sysfs清楚了解设备的系统状况
=>返回专栏总目录<= 文章目录 1.不敢高声语,恐惊天上人:sysfs目的 2.窥一斑而知全豹:sysfs目录介绍 3.千丝万缕:sysfs中要素的关系 4.数据观星:sysfs中相关结 ...
- RK3399平台开发系列讲解(内核入门篇)1.46、RTC驱动开发
平台 内核版本 安卓版本 RK3399 Linux4.4 Android7.1
- RK3399平台开发系列讲解(内核入门篇)1.18、 Sysfs设备驱动管理
- RK3399平台开发系列讲解(内核入门篇)1.42、Linux 文件系统是怎么工作的?
平台 内核版本 安卓版本 RK3399 Linux4.4 Android7.1
- RK3399平台开发系列讲解(内核入门篇)1.53、platform平台设备
- RK3399平台开发系列讲解(内核入门篇)1.48、LDM数据结构详解
- RK3399平台开发系列讲解(内核入门篇)1.3、从内核的角度看外设芯片的驱动
=>返回专栏总目录<= 文章目录 一.芯片的基本功能模块 1.1.复位 1.2.中断 1.3.接口 2.一个完整的芯片驱动 2.1.初始化 2.2.芯片的正常工作状态 2.3.suspen ...
- openlayers入门开发系列之地图属性查询篇
本篇的重点内容是利用openlayers实现地图属性查询功能,效果图如下: 实现思路: 模糊查询点击事件 //模糊查询 $("#swatchQuery").bind("c ...
- 【微信小程序开发•系列文章一】入门
本系统文章主要有以下几篇: <[微信小程序开发•系列文章一]入门> <[微信小程序开发•系列文章二]视图层> <[微信小程序开发•系列文章三]数据层> <[微 ...
最新文章
- Java String,StringBuilder和StringBuffer的区别 StringBuilder StringBuffer String
- Java设计模式-中介者模式
- centos7 下通过nginx+uwsgi部署django应用
- C++总结笔记(七)—— 运算符重载
- 多台电脑集群运算_一个分布式服务器集群架构方案
- nginx 优化,突破十万并发
- maven自定义本地仓库目录
- 永久免费http升级到https
- Java中使用KCP协议
- python机器学习案例系列教程——文档分类器,朴素贝叶斯分类器,费舍尔分类器
- 同济大学 线性代数 第六版 pdf_【课后习题答案】工程数学线性代数同济第六版+课后习题答案...
- 2021华为软挑赛题_思路分析——实时更新,做多少更多少(二)
- Android M 设置里面关于手机型号的修改
- 压缩软件如何删除压缩包密码(zip、rar、7-zip),忘记密码如何删除密码?
- 微信支付及支付宝支付开发指南
- 托业考试 与 托福考试
- Android权限 - 权限分类
- 周末作业-循环练习题
- antd DatePicker 组件 月份和星期显示英文
- ZigBee的无线通信与网络组建
热门文章
- 安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错”(错误原因、详细分析及解决方法)以及在Windows Server2012上安装.NET Framework 3
- android跑马灯源码,Android跑马灯的简单实现方式
- 【读书笔记】深入浅出数据分析
- SSH学习之一 OpenSSH基本使用
- c语言程序设计二级考试哪些题型,计算机二级考试题型
- java-高级编程课-实验题集标答整理
- 私塾 java_JAVA私塾
- informix数据库unload下载数据和load上传数据
- 该更新一下你的密码字典了
- 安装2000服务器显示文件挂起,MS sql server 2000安装中的提示挂起的解决方案。