1. 前言
之前写了几篇关于
redux
和react-redux
文章,链接如下
redux-基础
redux-实战
react-redux 基础
react-redux-reducer拆分
但是反应还是似懂非懂,这次我就换种方式再来捋一遍,我就不信,讲不明白,如果看不懂,不是读者们技术不行,是我自己没有讲明白
2. 是什么 what redux
Redux
是一个使用叫做“action”
的事件来管理
和更新
应用状态
的模式和工具库 ;
它以集中式Store
(centralized store)的方式对整个应用中使用的状态
进行集中管理
,其规则确保状态只能以可预测
的方式更新。
简单来说就是 类似
vuex
用来管理应用程序中状态数据的
3. 应用场景
1.在应用的大量地方,都存在大量的状态
2.应用状态会随着时间的推移而频繁更新
3.更新该状态的逻辑可能很复杂
4.中型和大型代码量的应用,很多人协同开发
简单来说就是你有些数据需要多个页面或者组件共享的时候,就该想到状态管理了
react
对应的 是react-redux
和mobx
,因为这俩比较流行,
多说一句,其实这俩可以在一个项目中同时使用,至于为啥用两个,无非就是可能后来填坑的人,不懂之前的用法,就写一个自己会的而已,虽然我不建议这么做,但是有些外包确实就是这样
4. 环境安装
npm install react-redux
我这里具体是 "react-redux": "^7.2.4"
5. why 如何管理
1.应用的整体
全局状态
以对象树
的方式存放于单个 store
。
2.唯一改变
状态树(state tree)的方法
是创建action
3.一个描述发生了什么
的对象,并将其dispatch
给store
。
- 要指定状态树如何
响应 action
来进行更新,你可以编写纯reducer 函数
,这些函数根据旧 state
和action
来计算新 state
三大原则
单一数据源
整个应用的state被存储在一棵object tree 中,并且这个object tree 中只存在唯一一个的store中.state是只读的
唯一改变state的方式就是除非action,action是一个用于描述已发生事件的普通对象使用纯函数来执行修改
为了描述action 如何改变state tree,你需要编写纯的reducers
6. How 杂用
6.1 入口 index.js 配置
// redux存储器
import store from "./store"
// 注入store
import { Provider } from 'react-redux'
<Provider store={store}>
<App />
</Provider>
6.2 配置解析
store
目录是自己新建的和 入口index.js
同级- 新建store文件
store/index.js
,当然名字你自己随便起叫store.js
也行,这作为我们应用程序的单个store
- 引入
Provider
对象 包裹起来我们的App
应用程序组件- 通过
store
属性全局注入我们的store
,这个就是上面说的单个store
7. store配置
src/store/index.js
7.1 配置
import { createStore } from "redux";
let defaultState = {
counter:0
}
function reducer(state=defaultState,action){}
let store = createStore(reducer)
export default store
7.2 vuex VS react-redux
let store = createStore({
state:{},
mutations:{}
});
观察下
vuex
的配置 对比起来好理解
8. 配置解析----createStore
1.需要从
redux
引入创建函数createStore
2.createStore
需要1个参数reducer
8.1 what reducer 啥玩意?
简单来说: 类似一个中间处理器 ,记录状态的改变
不简单的官方来说
reducer
是一个函数
,接收当前的state
和一个action
对象,必要时决定如何更新状态
,并返回新状态
。
函数语法是:(state, action) => newState。
你可以将reducer
视为一个事件监听器,它根据接收到的 action(事件)类型处理事件。
8.2 Reducer 必需符合以下规则
1.仅使用 state 和 action 参数计算新的状态值
2.禁止直接修改 state。必须通过复制现有的 state 并对复制的值进行更改的方式来做 不可变更新(immutable updates)。
3.禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
不能执行有副作用的操作,如API请求和路由跳转
不能调用非纯函数 如Date.now() Math.random()
9.reducer
需要状态配置信息参数(状态的初始值,以及修改状态的方法)
需要2个参数
第一个参数state
: 需要管理的数据状态初值
第二个参数action
:描述发生了什么
9.1 核心代码
let defaultState = {
counter:0
}
function reducer(state=defaultState,action){
switch (action.type){
case "counter/incremented":{
// 如果 state 是普通对象,永远不要修改它
// 方式一
let tempState = JSON.parse(JSON.stringify(state));
tempState.counter += action.payload
return tempState
}
case "counter/decremented":{
return{
...state,
counter:state.counter - action.payload
}
}
default:{
console.log("switch 默认")
return state
}
}
}
9.2 action 概念
action
是一个具有type
字段的普通JavaScript 对象
描述应用程序中发生了什么的事件.
action
类似vuex
必须通过commit
提交mutations
根据类型来修改state
9.3 type 解析
1.
mutations
通过commit
提交的时候 其实也有个type
类型
react-redux
的action
也有这个类型
3.type
字段是一个字符串,给这个action
一个描述性的名字
推荐type
写法
比如"counter/incremented"
。我们通常把那个类型的字符串写成“域/事件名称”,
其中第一部分是这个 action 所属的特征或类别
,
第二部分是发生的具体事情
。
我们不能直接改变
state
,如果直接改,会让数据流的变化不可预测
9.4 state 修改方式- -JSON
1.通过
JSON
相关API
实现简易的深拷贝
payload
载荷直接作为action
的属性来接收参数,名字可以随便起
case "counter/incremented":{
// 方式一
let tempState = JSON.parse(JSON.stringify(state));
tempState.counter += action.payload
return tempState
}
9.5 state修改方式 --展开运算符
case "counter/decremented":{
return{
...state,
counter:state.counter - action.payload
}
}
运用了 展开运算符
会覆盖掉之前的值
1.png
10. store梳理
1.
Store
就是用来维持应用所有的state 树
的一个对象
2.改变 store
内 state 的惟一
途径是对它dispatch
一个 action。
3.Store
不是类。它只是有几个方法的对象
。 要创建它,只需要把根部的reducing
函数 传递给createStore
。
4.调用createStore
的时候,reducer
会被默认执行一次,完成对状态的初始化(执行里面的default
)
11. 更新 state dispatch
11.1 基本概念
(Store): 保存了应用所有 state 的对象。
Redux store
有一个方法叫dispatch
。
更新 state
的唯一方法是调用store.dispatch()
并传入一个action 对象
。
store
将执行所有reducer 函数
并计算出更新
后的state
11.2 核心代码
store.dispatch({
type:"counter/incremented",
payload:10
})
store.dispatch({
type:"counter/decremented",
payload:5
})
type
类型和reducer
里面保持一致
11.3 dispatch 理解
dispatch
一个action
可以形象的理解为 "触发一个事件
"。
发生了一些事情,我们希望store
知道这件事。
Reducer
就像事件监听器
一样,当它们收到关注的 action 后,它就会更新
state `
12. 获取 state 状态
调用 getState() 可以获取新 state。
console.log("获取修改前store状态:",store.getState())
13. 监听 state 改变
也可以 通过
subscribe
监听state
的变化,然后更新 UI
。
监听 store.subscribe(()=>{}()
销毁 unsubscribe();
let unsubscribe = store.subscribe(()=>{
n++;
console.log("状态改了",n);
// store.getState()
})
// 一般在组件销毁的时候使用 unmounted
unsubscribe();
14. 完整代码
能看到这里的,都是具备技术大牛的潜质,付上简易代码
import { createStore } from "redux";
/* redux的核心配置,中间处理器 ,记录状态的改变
let defaultState = {
counter:0
}
// 需要状态配置信息参数(状态的初始值,以及修改状态的方法)
function reducer(state=defaultState,action){
switch (action.type){
case "counter/incremented":{
// state 永远不要修改它
// 方式一
let tempState = JSON.parse(JSON.stringify(state));
tempState.counter += action.payload
return tempState
}
case "counter/decremented":{
return{
...state,
counter:state.counter - action.payload
}
}
default:{
console.log("switch 默认")
return state
}
}
}
//调用createStore的时候,reducer会被默认执行一次,完成对状态的初始化(执行里面的default)
let store = createStore(reducer)
export default store
/*
vue这样写的 借鉴的就是redux
let store = createStore({
state:{},
mutations:{}
});
*/
// ************** 获取状态
console.log("获取修改前store状态:",store.getState())
var n = 0 ;
// 返回值就是销毁自己的方法
let unsubscribe = store.subscribe(()=>{
n++;
console.log("状态改了",n);
// store.getState()
})
// 一般在组件销毁的时候使用 unmounted
unsubscribe();
// 修改状态
store.dispatch({
type:"counter/incremented",
payload:10
})
store.dispatch({
type:"counter/decremented",
payload:10
})
15. 数据流图示
redux.gif
16. 后记
梳理了
N
遍,思维导图梳理,文章梳理,markdown梳理讲课步骤,代码也写了N
多遍,我自己算是比较明白了
不知道讲的明不明白,大概看了下,可能文章太长了,现在焦虑的心理,可能对这种长文章顺手就关了,如果看到,希望对你有帮助
参考资料
redux基础
redux-实战
react-redux 基础
react-redux-reducer拆分
react-redux
网友评论