概念:
Redux 是一个使用”actions”的事件管理和更新应用状态的模式和工具库,以集中式Store的方式对整个应用中使用的状态进行集中管理,其规则确保状态只能以可预测的方式更新
Redux 在以下情况下更有用:
- 在应用的大量地方,都存在大量的状态
- 应用状态会随着时间的推移而频繁更新
- 更新该状态的逻辑可能很复杂
- 中型和大型代码量的应用,很多人协同开发
store:
保存应用程序的全局state的容器,是一个Js对象,store是通过传入一个reducer来创建的,并且有一个名为getState的方法,它返回当前状态值
1 | import {configureStore} from "@reduxjs/toolkit" |
action:
是一个具有type字段的普通js对象,可以将action视为描述应用程序中发生了什么事件,type字段是一个字符串,给这个action一个描述性的名字,比如”todos/todoAdded”(域/事件名称),第一部分是这个action所属的特征和类别,第二部分是具体发生的具体事情
action对象可以有其他字段,将其放在名为payload的字段中
action创建函数:就是生成action的方法,action创建函数只是简单返回一个action
1 | function addTodo(text) { |
reducers
reducer是一个函数,接收当前的state和一个action对象,必要时决定如何更新状态,并返回新状态,函数签名(state,action)=>newState,可以将reducer视为一个事件监听器,它根据接收到的action类型处理事件
reducer必须是一个纯函数:
- 仅使用
state
和action
参数计算新的状态值 - 禁止直接修改
state
。必须通过复制现有的state
并对复制的值进行更改的方式来做 不可变更新(immutable updates)。 - 禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
reducer 函数内部的逻辑通常遵循以下步骤:
- 检查 reducer 是否关心这个 action
- 如果是,则复制 state,使用新值更新 state 副本,然后返回新 state
- 否则,返回原来的 state 不变
dispatch
更新state的唯一方法是调用store.dispatch()并传入一个action对象,store将执行所有reducer函数并计算出更新后的state,调用getState()可以获取更新的state
1 | store.dispatch({type:'counter/increamented'}) |
Selectors:
Selector函数可以从store状态树中提取指定的片段,随着应用变大,遇到不同应用程序的不同部分需要读取相同数据,selector可以避免重复这样的状态逻辑
1 | const selectCounterValue=state=>state.value |
核心概念:
单一数据源:应用程序的全局状态作为对象存储在单个 store 中。任何给定的数据片段都应仅存在于一个位置,而不是在许多位置重复。
state只读:
更改状态的唯一方法是 dispatch 一个 action,这是一个描述所发生情况的对象。
这样,UI 就不会意外覆盖数据,并且更容易跟踪发生状态更新的原因。由于 actions 是普通的 JS 对象,因此可以记录、序列化、存储这些操作,并在以后重放这些操作以进行调试或测试。
使用reducer纯函数进行更改:
Reducers 是纯函数,它们采用旧 state 和 action,并返回新 state。
redux数据流:
单向数据流:
root reducer函数创建Redux store=>store调用一次root reducer,并将返回值保存为它的初始state=>UI首次渲染时,UI组件访问Redux store的当前state,并将数据渲染为内容,监听store的更新:
应用更新=>dispatch一个action到Redux store=>store用之前的state和当前的action再次运行reducer函数,并将返回值保存为新的state=>store通知所有订阅过的UI,通知store更新=>每个订阅过store数据的UI组件就会检查它们需要的state部分是否被更新=>发现更新,每个组件强制使用新数据渲染,更新网页
明确两个概念:
UI组件:不能使用任何redux的api,只负责页面的呈现,交互
容器组件:负责和redux通信,将结果交给UI组件
- 创建一个容器组件:靠react-redux的connect函数,connect(mapStateToProps,mapDispatchToProps)(UI组件)
- mapStateToProps:映射状态:返回值时一个对象
- mapDispatchToProps:映射操作状态的方法,返回值是一个对象
1 | import { connect } from 'react-redux' |
- 容器组件中的store是靠props传进去,而不是在容器组件中直接引入
优化:
- 容器组件和UI组件整合为一个文件
- 不用给容器组件传递store,给
包裹一个 即可 - 使用react-redux后不用自己检测redux状态的变化,容器组件自己完成这个工作
- mapDispatchToProps写成一个对象
1 | { |
总结:一个组件与redux打交道步骤:
- 定义UI组件不暴露
- 引入connect生成一个容器组件:connect(state=>{key:value}),{key:xxxAction})(UI组件)
- 在UI组件中通过this.props.xxx读取和操作状态
todoList例子: