1
1
---
2
- title : 把状态逻辑移到 Reducer 中
2
+ title : 迁移状态逻辑至 Reducer 中
3
3
translators :
4
4
- qinhua
5
5
- yyyang1996
@@ -60,7 +60,7 @@ export default function TaskBoard() {
60
60
61
61
return (
62
62
<>
63
- < h1> 布拉格的行程 < / h1>
63
+ < h1> 布拉格的行程安排 < / h1>
64
64
< AddTask
65
65
onAddTask= {handleAddTask}
66
66
/ >
@@ -77,7 +77,7 @@ let nextId = 3;
77
77
const initialTasks = [
78
78
{ id: 0 , text: ' 参观卡夫卡博物馆' , done: true },
79
79
{ id: 1 , text: ' 看木偶戏' , done: false },
80
- { id: 2 , text: ' 列侬墙图片 ' , done: false },
80
+ { id: 2 , text: ' 打卡列侬墙 ' , done: false },
81
81
];
82
82
```
83
83
@@ -227,8 +227,7 @@ function handleDeleteTask(taskId) {
227
227
* ` handleChangeTask(task) ` 在用户切换任务或点击 “保存” 时被调用。
228
228
* ` handleDeleteTask(taskId) ` 在用户点击 “删除” 时被调用。
229
229
230
- 使用 reducers 管理状态与直接设置状态略有不同。它不是通过设置状态告诉 React “要做什么”,而是通过事件处理程序 dispatch 一个 “action” 来指明 “用户刚刚做了什么”。(状态更新逻辑在其他地方!)
231
- 因此,我们不再通过事件处理器直接“设置任务”,而是 dispatch 一个 “添加/修改/删除任务” 的 action。这更加符合用户的思维。
230
+ 使用 reducers 管理状态与直接设置状态略有不同。它不是通过设置状态告诉 React “要做什么”,而是通过事件处理程序 dispatch 一个 “action” 来指明 “用户刚刚做了什么”。(状态更新逻辑在其他地方!)因此,我们不再通过事件处理器直接“设置任务”,而是 dispatch 一个 “添加/修改/删除任务” 的 action。这更加符合用户的思维。
232
231
233
232
``` js
234
233
function handleAddTask (text ) {
@@ -269,6 +268,7 @@ function handleDeleteTask(taskId) {
269
268
```
270
269
271
270
它是一个普通的 JavaScript 对象。它的结构是由你决定的,但通常来说,它应该至少包含可以表明 * 发生了什么事情* 的信息。(在后面的步骤中,你将会学习如何添加一个 ` dispatch ` 函数。)
271
+
272
272
<Convention conventionFor =" action objects " >
273
273
274
274
action 对象可以有多种结构。按照惯例,我们通常会添加一个字符串类型的 ` type ` 字段来描述发生了什么,并通过其它字段传递额外的信息。` type ` 是特定于组件的,在这个例子中 ` added ` 和 ` addded_task ` 都可以。选一个能描述清楚发生的事件的名字!
@@ -328,6 +328,7 @@ function tasksReducer(tasks, action) {
328
328
```
329
329
330
330
> 由于 ` reducer ` 函数接受 ` state ` (tasks)作为参数,因此你可以 ** 在组件之外声明它** 。** 这减少了代码的缩进级别,提升了代码的可读性。
331
+
331
332
<Convention conventionFor =" reducer functions " >
332
333
333
334
上面的代码使用了 ` if/else ` 语句,但是在 reducers 中使用 [ switch 语句] ( https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/switch ) 是一种惯例。两种方式结果是相同的,但 ` switch ` 语句读起来一目了然。在本文档的后面部分我们会像这样使用:
@@ -370,7 +371,6 @@ function tasksReducer(tasks, action) {
370
371
371
372
<DeepDive title =" 为什么叫它 reducer 呢? " >
372
373
373
-
374
374
尽管 ` reducer ` 可以 “减少” 组件内的代码量,但它实际上是以数组上的 [ ` reduce() ` ] ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce ) 方法命名的。
375
375
376
376
` reduce() ` 允许你将数组中的多个值 “累加” 成一个值:
@@ -396,7 +396,7 @@ let actions = [
396
396
{ type: ' added' , id: 1 , text: ' 参观卡夫卡博物馆' },
397
397
{ type: ' added' , id: 2 , text: ' 看木偶戏' },
398
398
{ type: ' deleted' , id: 1 },
399
- { type: ' added' , id: 3 , text: ' 列侬墙图片 ' },
399
+ { type: ' added' , id: 3 , text: ' 打卡列侬墙 ' },
400
400
];
401
401
402
402
let finalState = actions .reduce (
@@ -525,7 +525,7 @@ export default function TaskBoard() {
525
525
526
526
return (
527
527
<>
528
- < h1> 布拉格的行程 < / h1>
528
+ < h1> 布拉格的行程安排 < / h1>
529
529
< AddTask
530
530
onAddTask= {handleAddTask}
531
531
/ >
@@ -569,7 +569,7 @@ let nextId = 3;
569
569
const initialTasks = [
570
570
{ id: 0 , text: ' 参观卡夫卡博物馆' , done: true },
571
571
{ id: 1 , text: ' 看木偶戏' , done: false },
572
- { id: 2 , text: ' 列侬墙图片 ' , done: false }
572
+ { id: 2 , text: ' 打卡列侬墙 ' , done: false }
573
573
];
574
574
```
575
575
@@ -715,7 +715,7 @@ export default function TaskBoard() {
715
715
716
716
return (
717
717
<>
718
- < h1> 布拉格的行程 < / h1>
718
+ < h1> 布拉格的行程安排 < / h1>
719
719
< AddTask
720
720
onAddTask= {handleAddTask}
721
721
/ >
@@ -732,7 +732,7 @@ let nextId = 3;
732
732
const initialTasks = [
733
733
{ id: 0 , text: ' 参观卡夫卡博物馆' , done: true },
734
734
{ id: 1 , text: ' 看木偶戏' , done: false },
735
- { id: 2 , text: ' 列侬墙图片 ' , done: false },
735
+ { id: 2 , text: ' 打卡列侬墙 ' , done: false },
736
736
];
737
737
```
738
738
@@ -876,11 +876,11 @@ ul, li { margin: 0; padding: 0; }
876
876
877
877
Reducers 并非没有缺点!以下是比较它们的几种方法:
878
878
879
- - ** 代码体积:** 通常,在使用 ` useState ` 时,一开始只需要编写少量代码。而 ` useReducer ` 必须提前编写 reducer 函数和需要调度的 actions。但是,当多个事件处理程序以相似的方式修改 state 时,` useReducer ` 可以减少代码量。
880
- - ** 可读性:** 当状态更新逻辑足够简单时,` useState ` 的可读性还行。但是,一旦逻辑变得复杂起来,它们会使组件变得臃肿且难以阅读。在这种情况下,` useReducer ` 允许你将状态更新逻辑与事件处理程序分离开来。
881
- - ** 可调试性:** 当使用 ` useState ` 出现问题时, 你很难发现具体原因以及为什么。 而使用 ` useReducer ` 时, 你可以在 reducer 函数中通过打印日志的方式来观察每个状态的更新,以及为什么要更新(来自哪个 ` action ` )。 如果所有 ` action ` 都没问题,你就知道问题出在了 reducer 本身的逻辑中。 然而,与使用 ` useState ` 相比,你必须单步执行更多的代码。
882
- - ** 可测试性:** reducer 是一个不依赖于组件的纯函数。这就意味着你可以单独对它进行测试。一般来说,我们最好是在真实环境中测试组件,但对于复杂的状态更新逻辑,针对特定的初始状态和 ` action ` ,断言 reducer 返回的特定状态会很有帮助。
883
- - ** 个人偏好:** 并不是所有人都喜欢用 reducer,没关系,这是个人偏好问题。你可以随时在 ` useState ` 和 ` useReducer ` 之间切换,它们能做的事情是一样的!
879
+ * ** 代码体积:** 通常,在使用 ` useState ` 时,一开始只需要编写少量代码。而 ` useReducer ` 必须提前编写 reducer 函数和需要调度的 actions。但是,当多个事件处理程序以相似的方式修改 state 时,` useReducer ` 可以减少代码量。
880
+ * ** 可读性:** 当状态更新逻辑足够简单时,` useState ` 的可读性还行。但是,一旦逻辑变得复杂起来,它们会使组件变得臃肿且难以阅读。在这种情况下,` useReducer ` 允许你将状态更新逻辑与事件处理程序分离开来。
881
+ * ** 可调试性:** 当使用 ` useState ` 出现问题时, 你很难发现具体原因以及为什么。 而使用 ` useReducer ` 时, 你可以在 reducer 函数中通过打印日志的方式来观察每个状态的更新,以及为什么要更新(来自哪个 ` action ` )。 如果所有 ` action ` 都没问题,你就知道问题出在了 reducer 本身的逻辑中。 然而,与使用 ` useState ` 相比,你必须单步执行更多的代码。
882
+ * ** 可测试性:** reducer 是一个不依赖于组件的纯函数。这就意味着你可以单独对它进行测试。一般来说,我们最好是在真实环境中测试组件,但对于复杂的状态更新逻辑,针对特定的初始状态和 ` action ` ,断言 reducer 返回的特定状态会很有帮助。
883
+ * ** 个人偏好:** 并不是所有人都喜欢用 reducer,没关系,这是个人偏好问题。你可以随时在 ` useState ` 和 ` useReducer ` 之间切换,它们能做的事情是一样的!
884
884
885
885
如果你在修改某些组件状态时经常出现问题或者想给组件添加更多逻辑时,我们建议你还是使用 reducer。当然,你也不必整个项目都用 reducer,这是可以自由搭配的。你甚至可以在一个组件中同时使用 ` useState ` 和 ` useReducer ` 。
886
886
@@ -958,7 +958,7 @@ export default function TaskBoard() {
958
958
959
959
return (
960
960
<>
961
- < h1> 布拉格的行程 < / h1>
961
+ < h1> 布拉格的行程安排 < / h1>
962
962
< AddTask
963
963
onAddTask= {handleAddTask}
964
964
/ >
@@ -975,7 +975,7 @@ let nextId = 3;
975
975
const initialTasks = [
976
976
{id: 0 , text: ' 参观卡夫卡博物馆' , done: true },
977
977
{id: 1 , text: ' 看木偶戏' , done: false },
978
- {id: 2 , text: ' 列侬墙图片 ' , done: false },
978
+ {id: 2 , text: ' 打卡列侬墙 ' , done: false },
979
979
];
980
980
```
981
981
0 commit comments