Skip to main content

Three Principles

Redux Toolkit

本页介绍 Redux Toolkit 所基于的 Redux 底层机制。在实际应用中,通常会使用 Redux Toolkit 的 configureStore 和 createSlice,而不是自行编写这些底层代码。不过,了解这些 API 的底层原理仍然很有价值。

了解如何使用当前推荐的方式编写 Redux 应用,请参阅 Redux Essentials 教程。如需更新现有代码,请参阅迁移到现代 Redux。

Redux can be described in three fundamental principles:

单一数据源​

你的应用的全局状态存储在一个单一的store中的对象树里。

这使得创建通用应用变得容易,因为你可以将服务器端的状态序列化并在客户端恢复,且无需额外编码。单一的状态树也让调试或检查应用变得更简单;它还允许你在开发过程中持久化应用的状态,从而实现更快的开发周期。一些传统上难以实现的功能——例如撤销/重做——如果所有状态都存储在单个树中,变得异常简单。

console.log(store.getState())

/* 打印结果
{
visibilityFilter: 'SHOW_ALL',
todos: [
{
text: '考虑使用 Redux',
completed: true,
},
{
text: '把所有状态存储在单一树中',
completed: false
}
]
}
*/

状态只读​

更改状态的唯一方式是发出一个描述发生了什么的action对象。

这确保视图或网络回调绝不会直接写入状态。相反,它们表达了一个意图去转换状态。因为所有更改都是集中进行且按严格顺序依次发生,所以没有需要担心的微妙竞态条件。由于 actions 只是普通对象,它们可以被记录、序列化、存储,之后可以重新播放用于调试或测试。

store.dispatch({
type: 'COMPLETE_TODO',
index: 1
})

store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: 'SHOW_COMPLETED'
})

通过纯函数进行更改​

为了指定状态树如何根据 action 转换,你需要编写纯reducer。

Reducers 是纯函数,接收上一个状态和一个动作,返回下一个状态。记住要返回新的状态对象,而不是修改之前的状态。你可以从单一 reducer 开始,随着应用的增长,拆分成管理状态树特定部分的小 reducers。因为 reducers 只是函数,你可以控制它们被调用的顺序,传递额外数据,甚至创建可复用的 reducer 来完成诸如分页等常见任务。

function visibilityFilter(state = 'SHOW_ALL', action) {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}

function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
text: action.text,
completed: false
}
]
case 'COMPLETE_TODO':
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: true
})
}
return todo
})
default:
return state
}
}

import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({ reducer: { visibilityFilter, todos } })

就是这样!现在你明白 Redux 的核心理念了。