主题
Immer 中间件
¥Immer middleware
Immer 中间件使你能够以更方便的方式使用不可变状态。此外,使用 Immer,你可以简化 Zustand 中不可变数据结构的处理。
¥The Immer middleware enables you to use immutable state in a more convenient way. Also, with Immer, you can simplify handling immutable data structures in Zustand.
安装
¥Installation
为了在 Zusand 中使用 Immer 中间件,你需要将 Immer 安装为直接依赖。
¥In order to use the Immer middleware in Zustand, you will need to install Immer as a direct dependency.
bash
npm install immer
用法
¥Usage
(请注意 Typescript 指南 中提到的类型参数后面的额外括号)。
¥(Notice the extra parentheses after the type parameter as mentioned in the Typescript Guide).
更新简单状态
¥Updating simple states
ts
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
type State = {
count: number
}
type Actions = {
increment: (qty: number) => void
decrement: (qty: number) => void
}
export const useCountStore = create<State & Actions>()(
immer((set) => ({
count: 0,
increment: (qty: number) =>
set((state) => {
state.count += qty
}),
decrement: (qty: number) =>
set((state) => {
state.count -= qty
}),
})),
)
更新复杂状态
¥Updating complex states
ts
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
interface Todo {
id: string
title: string
done: boolean
}
type State = {
todos: Record<string, Todo>
}
type Actions = {
toggleTodo: (todoId: string) => void
}
export const useTodoStore = create<State & Actions>()(
immer((set) => ({
todos: {
'82471c5f-4207-4b1d-abcb-b98547e01a3e': {
id: '82471c5f-4207-4b1d-abcb-b98547e01a3e',
title: 'Learn Zustand',
done: false,
},
'354ee16c-bfdd-44d3-afa9-e93679bda367': {
id: '354ee16c-bfdd-44d3-afa9-e93679bda367',
title: 'Learn Jotai',
done: false,
},
'771c85c5-46ea-4a11-8fed-36cc2c7be344': {
id: '771c85c5-46ea-4a11-8fed-36cc2c7be344',
title: 'Learn Valtio',
done: false,
},
'363a4bac-083f-47f7-a0a2-aeeee153a99c': {
id: '363a4bac-083f-47f7-a0a2-aeeee153a99c',
title: 'Learn Signals',
done: false,
},
},
toggleTodo: (todoId: string) =>
set((state) => {
state.todos[todoId].done = !state.todos[todoId].done
}),
})),
)
陷阱
¥Gotchas
在本节中,你将找到在将 Zustand 与 Immer 一起使用时需要记住的一些事项。
¥In this section you will find some things that you need to keep in mind when using Zustand with Immer.
我的订阅未被调用
¥My subscriptions aren't being called
如果你使用的是 Immer,请确保你确实遵循了 规则 Immer。
¥If you are using Immer, make sure you are actually following the rules of Immer.
例如,你必须添加 [immerable] = true
才能使 类对象 工作。如果你不这样做,Immer 仍会改变对象,但不会作为代理,因此它也会更新当前状态。Zustand 检查状态是否真的发生了变化,因此由于当前状态和下一个状态都相等(如果你没有正确执行此操作),Zustand 将跳过调用订阅。
¥For example, you have to add [immerable] = true
for class objects to work. If you don't do this, Immer will still mutate the object, but not as a proxy, so it will also update the current state. Zustand checks if the state has actually changed, so since both the current state and the next state are equal (if you don't do it correctly), Zustand will skip calling the subscriptions.
CodeSandbox 演示
¥CodeSandbox Demo