用浅显易懂的方式向五岁小孩解释 Redux | Redux 速查表
概括
这篇文章将通过一个精彩的真实案例,帮助你复习/学习 Redux 的基本概念。那么,让我们开始吧!
Redux 是predictable state container用于 JavaScript 应用程序的框架。
在这个语境中,这个术语的predictable意思是,使用 Redux,你将知道应用程序中的每一个操作会做什么以及状态将如何变化。
redux 应用中基本上有三个参与者,即store,actions和reducers。
Redux 中的一切都是单向的,即state -> action -> reducer -> state -> action -> reducer -> state ...
它可以帮助你编写行为一致的应用程序。
让我们以银行业务流程为例来了解这些参与者。
店铺
假设你想从银行账户里取钱。你会去银行办理。银行有金库,里面存放着所有的钱。
银行金库之于银行,正如 Redux Store 之于 Redux。
拥有单一数据源:整个应用程序的状态都存储在单个 Redux store 中的对象树中。
等等,state顺便问一下,这是什么?State它只不过是由管理的值而已store。它money之于,bank正如它state之于store。
简单来说,使用 Redux 时,建议将应用程序状态存储在由 Redux store 管理的单个对象中。
一个应用程序状态对象由一个商店管理
状态是只读的:改变状态的唯一方法是发出一个动作,即一个描述发生了什么的对象。
行动
行动体现了你的意图。
例如,要取款,你需要向收银员传达你的意图,即取款。
{
type: "WITHDRAW_MONEY",
amount: "$5,000"
}
改变状态的唯一方法是向描述所发生情况的对象发出一个动作。
减速器
收银员之于银行,正如 reducer 之于 Redux。
如果你想更新应用程序的状态,你需要将你的操作传递给 reducer。这个过程通常被称为dispatching an action.
reducer 知道该怎么做。在这个例子中,它会将你的 action 传递给 WITHDRAW_MONEY 操作,并确保你收到你的钱。
在 Redux 中,你花费的金钱就是你的状态。因此,你的 reducer 知道该怎么做,并且总是返回你的新状态。
要指定状态树如何通过 action 进行转换,你需要编写纯 reducer。
通过这个类比,你现在应该对最重要的 Redux 参与者有所了解了:`the` store、`the`reducer和 `an` action。
以下是创建 Redux store 的代码:
import { createStore } from "redux"; //an import from the redux library
const store = createStore(); // an incomplete solution - for now.
降维器始终与存储器“对话”。存储器和降维器是好伙伴,始终保持同步。
Reducer 是唯一必须传递给它的参数。createStore()
根据 Redux 官方文档:
Reducer 是 Redux 中最重要的概念。Reducer
也称为归约函数,如果您熟悉 Array.reduce() 方法,那么您可能已经在使用 reducer 了。
let arr = [1,2,3,4,5]
let sum = arr.reduce((x,y) => x + y)
console.log(sum) //15
传递给该函数的参数arr.reduce称为 reducer。
在本例中,reducer 接收两个值:累加器和当前值,其中 x 是累加器,y 是当前值。
同样,Redux Reducer 也只是一个函数。这个函数接受两个参数。第一个参数是应用程序的状态(STATE),另一个参数是操作(ACTION)。
但是传递给 REDUER 的 STATE 和 ACTION 从何而来呢?
Array.reduce 方法负责将所需的参数 x 和 y 传递给函数参数(即 reducer)。所以,这些参数并非凭空产生的。
Reduxreducer也被传递给了createStore工厂函数。与 `Array.reduce()` 类似,`createStore()` 负责将参数传递给 reducer。reducer 总是会返回一些值。在最初的 `Array.reduce()` reducer 示例中,我们返回了累加器和当前值的总和。对于 Redux reducer,它总是返回应用程序的新状态。
initialState是传递给函数调用的第二个参数createStore。
每当您使用 创建一个 store 时createStore(),创建的 store 都会公开三个方法。- getState()store.getState() 将返回对象dispatch()- store.dispatch(action) 将分发一个 action subscribe()- 用于订阅以监视状态的更改/更新。
为了处理传递给 reducer 的操作,你通常会在 reducer 中编写一个 switch 语句。
它会切换操作类型,并根据传入的操作类型执行相应的操作。
操作类型全部用大写字母书写。虽然不是强制性的,但这在 Redux 社区中是一种相当流行的风格。
首先,它们的 type 字段都相同。如果我们需要在多个地方分发这些 action,就得到处复制粘贴。这不太好。尤其因为保持代码简洁(DRY 原则)非常重要。
欢迎Action Creators!
动作创建器只是帮助你创建动作的函数。仅此而已。它们是返回动作对象的函数。
export function withdrawMoney (amount) {
return {
type: "WITHDRAW_MONEY",
amount: amount
}
}
通常的做法是将 Redux 应用的主要组件放在各自的文件夹/目录中。这里所说的组件指的是 `<script>`、`<script>`reducer和actions`<script> ` 标签store。
对于大型应用来说,这无疑是一种相当不错的做法。
在每个文件夹中创建一个 index.js 文件。这将是所有 Redux actor(reducer、store 和 actions)的入口点。
动作被分发后,会通过 reducer 进行处理。
切勿在 Reducer 中修改状态。
您不应该修改 Reducer 中接收到的状态。相反,您应该始终返回状态的新副本。
正道
export default (state, action) => {
switch (action.type) {
case "WITHDRAW_MONEY":
return {
...state,
amount: action.amount
};
default:
return state;
}
};
错误的方法
export default (state, action) => {
switch (action.type) {
case "WITHDRAW_MONEY":
state.amount = action.amount;
return state;
default:
return state;
}
};
得益于ES6价差运算符,...state……然而,技术领域会根据市场动态进行更新。action.text
Redux store,无论你创建什么 store,都有一个类似这样的 subscribe 方法:store.subscribe()。
传入的参数store.subscribe()是一个函数,每当状态更新时都会调用它。
// in app.js
const render = () => ReactDOM.render(<App />, document.getElementById("root"));
render();
// Any time there’s a successful update to the store, the <App/> will now be re-rendered with the new state values.
store.subscribe(render);
容器和组件
在 Redux 应用中,将组件拆分到两个不同的目录中是一种常见的模式。
所有直接与 Redux 交互的组件,无论是从 store 中检索状态,还是分发 action,都应该移到一个containers单独的目录中。
其他不与 Redux 交互的组件应该移到一个components单独的目录中。
还原器组成(多个还原器)
在应用程序中,通常会有多个 reducer,而不是只有一个 reducer 来处理所有状态操作。这些 reducer 随后会被合并成一个。
Reducer组合要求单个Reducer只负责状态对象中单个字段的状态更新。
另一点需要注意的是,每个Reducer的返回值仅针对其所代表的字段。
combineReducers要合并这些多个 reducer,我们需要使用辅助函数redux。
需要记住的一点是,在使用时combineReducers,每个 reducer 返回的值并不是应用程序的状态。
它只是value它们在状态对象中代表的特定键!
常量中的动作
创建一个新actions目录。同时,也创建一个常量文件夹。
在 constants 文件夹中,创建一个新文件 action-types.js。
此文件的唯一职责是保存动作类型常量。
概括
- 在开始编写代码之前,最好先规划好应用程序开发流程。
- 在状态对象中,务必避免使用嵌套实体。保持状态对象规范化。
- 将状态字段存储为对象确实有一些优势。但同时也要注意使用对象的问题,主要是缺乏顺序性。
lodash如果你选择在状态对象中使用对象而不是数组,那么这个实用工具库会非常方便。- 无论时间多么短暂,都要抽出一些时间来设计应用程序的状态对象。
- 使用 Redux,你不一定非要传递 props。你可以直接从 store 中访问 state 值。
- 在 Redux 应用中,始终保持清晰的文件夹结构,例如将所有主要的 Redux 组件放在各自的文件夹中。除了整体代码结构清晰之外,这样做还能让其他人更容易协作,因为他们更容易理解相同的文件夹结构。
- Reducer 组合非常实用,尤其是在应用规模扩大时。这可以提高可测试性,并减少难以追踪的错误发生的可能性。
- 对于 reducer 组合,请使用 redux 库中的 combineReducers。
- 传递给 combineReducers 函数的对象旨在模拟应用程序的状态,每个值都来自关联的 reducers。
- 始终将较大的组件分解成较小的、易于管理的部分。这样更容易逐步构建。