跳至主内容区

使用 produce

[非官方测试版翻译]

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

egghead.io lesson 3: Simplifying deep updates with _produce_

Immer 包导出了一个完成所有工作的 produce 函数。

produce(baseState, recipe: (draftState) => void): nextState

produce 接收一个基础状态(base state)和一个配方(recipe),该配方可用于对传入的 draft 执行所有期望的变更。Immer 的精妙之处在于 baseState 将保持不变,而 nextState 会反映对 draftState 所做的所有修改。

在配方内部,可以在 draft 对象上使用所有标准 JavaScript API,包括字段赋值、delete 操作,以及对数组、Map 和 Set 的变更操作(如 pushpopsplicesetsortremove 等)。

这些变更不必发生在根层级,而是允许在草稿(draft)内部的任意深度修改:draft.todos[0].tags["urgent"].author.age = 56

注意,配方函数本身通常不返回任何值。但若希望完全替换 draft 对象,可以返回一个新对象,详见返回新数据

示例

import {produce} from "immer"

const baseState = [
{
title: "Learn TypeScript",
done: true
},
{
title: "Try Immer",
done: false
}
]

const nextState = produce(baseState, draftState => {
draftState.push({title: "Tweet about it"})
draftState[1].done = true
})
// the new item is only added to the next state,
// base state is unmodified
expect(baseState.length).toBe(2)
expect(nextState.length).toBe(3)

// same for the changed 'done' prop
expect(baseState[1].done).toBe(false)
expect(nextState[1].done).toBe(true)

// unchanged data is structurally shared
expect(nextState[0]).toBe(baseState[0])
// ...but changed data isn't.
expect(nextState[1]).not.toBe(baseState[1])

术语

  • (base)state:传递给 produce 的不可变状态

  • recipeproduce 的第二个参数,定义基础状态应如何"变更"

  • draft:所有 recipe 的首个参数,作为原始基础状态的可安全变更代理(proxy)

  • producer:使用 produce 的函数,通常形式为 (baseState, ...arguments) => resultState

注意,配方函数的首个参数不必严格命名为 draft,可任意命名(如 users)。使用 draft 仅是约定俗成,暗示"此处允许变更"。