基础概念
一个Redux应该包含的主要部分
· state 数据源
· view 视图
· action UI
单向数据流(one-way data flow)
工作步骤: 定义state => 根据state中的数据渲染View => 事件发生时, 通过action更新并返回一个新的state => 根据新的state产生View
不可变性 Immutability
JavaScript 的对象(object)和数组(array)默认都是 mutable 的。即可以任意修改其中内容。内存中还是原来对象或数组的引用,但里面的内容变化了。
Redux 期望所有状态更新都是使用不可变的方式。
术语
Action
action 必须带有 type 字段, 它是一个对象,例如:
const addTodoAction = {
type: 'todos/todoAdded',
payload: 'Buy milk'
}
type: 名字
payload: 附加信息
Action Creator
可以用函数写:
const addTodo = text => {
return {
type: 'todos/todoAdded',
payload: text
}
}
这样不用每次都手动生成一个对象
Reducer
reducer是一个函数,接收state和action对象,内容是处理逻辑,返回新的状态。
Reducer 必需符合以下规则:
- 仅使用
state和action参数计算新的状态值 - 禁止直接修改
state。必须通过复制现有的state并对复制的值进行更改的方式来做 不可变更新(immutable updates) 。 - 禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
const initialState = { value: 0 }
function counterReducer(state = initialState, action) {
// 检查 reducer 是否关心这个 action
if (action.type === 'counter/increment') {
// 如果是,复制 `state`
return {
...state,
// 使用新值更新 state 副本
value: state.value + 1
}
}
// 返回原来的 state 不变
return state
}
Store
通过传入一个reducer创建,并且带有一个getState的方法。返回当前状态。
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({ reducer: counterReducer })
console.log(store.getState())
// {value: 0}
dispatch
更新state的唯一方法是调用store.dispatch()并传入一个对象。store将会执行所有的reducer计算出新的state,调用getState()可以获得新的state
store.dispatch({ type: 'counter/increment' })
console.log(store.getState())
// {value: 1}
更新数据的具体步骤
对于 Redux,我们可以将这些步骤分解为更详细的内容:
-
初始启动:
- 使用最顶层的 root reducer 函数创建 Redux store
- store 调用一次 root reducer,并将返回值保存为它的初始
state - 当 UI 首次渲染时,UI 组件访问 Redux store 的当前 state,并使用该数据来决定要呈现的内容。同时监听 store 的更新,以便他们可以知道 state 是否已更改。
-
更新环节:
- 应用程序中发生了某些事情,例如用户单击按钮
- dispatch 一个 action 到 Redux store,例如
dispatch({type: 'counter/increment'}) - store 用之前的
state和当前的action再次运行 reducer 函数,并将返回值保存为新的state - store 通知所有订阅过的 UI,通知它们 store 发生更新
- 每个订阅过 store 数据的 UI 组件都会检查它们需要的 state 部分是否被更新。
- 发现数据被更新的每个组件都强制使用新数据重新渲染,紧接着更新网页