初识Zustand
Zustand和React的区别
Conceptually, Zustand and Redux are quite similar, both are based on
an immutable state model. However, Redux requires your app to be
wrapped in context providers; Zustand does not.
在Redux中,你需要创建一个store来存储应用程序的状态,然后通过Provider将store传递给应用程序的其他组件。这意味着你需要在应用程序中引入Redux的上下文,并在需要访问状态的组件中使用connect函数来连接store。
而在Zustand中,你只需要定义一个状态,然后通过useStore hook来访问它。这意味着你不需要在组件中引入任何上下文,并且不需要使用connect函数来连接store。
用Zustand更新状态
使用set()
方法。对于flat updated
和deeply nested object
,更新方式存在不同。
flat updated的状态更新
type State = {
firstName: string
lastName: string
}
type Action = {
updateFirstName: (firstName: State['firstName']) => void
updateLastName: (lastName: State['lastName']) => void
//p.s. 如果函数没有特定的返回值,或者返回值没有意义,我们可以使用 void 类型
}
// Create your store, which includes both state and (optionally) actions
//p.s. 使用了 zustand 库中提供的 create 函数创建了一个名为 useStore 的自定义 Hook
const useStore = create<State & Action>((set) => ({
//p.s. 状态对象的类型定义为 State & Action,表示它具有 State 和 Action 两个类型的属性
//p.s. create 函数接受一个回调函数作为参数,该函数将用于初始化状态对象和操作。在回调函数中,使用 set 函数来更新状态对象的属性值
firstName: '',
lastName: '',
updateFirstName: (firstName) => set(() => ({ firstName: firstName })),
updateLastName: (lastName) => set(() => ({ lastName: lastName })),
//p.s. set 函数接受一个回调函数作为参数,并在该回调函数中返回一个新的状态对象
}))
// In consuming app
function App() {
// "select" the needed state and actions, in this case, the firstName value
// and the action updateFirstName
const [firstName, updateFirstName] = useStore(
//p.s. 调用 useStore 函数
(state) => [state.firstName, state.updateFirstName],
shallow
//p.s. 这个回调函数会接收状态对象作为参数,并返回一个数组,数组的第一个元素是 firstName 属性,第二个元素是 updateFirstName 函数。这个方式被称为 "selector",它将状态对象的某些属性和操作提取出来,使得可以在组件中有选择地使用它们。
//p.s. shallow 参数,它表示在比较状态对象是否发生变化时,只会比较对象的浅层属性,而不会递归比较对象的深层属性。
)
return (
<main>
<label>
First name
<input
// Update the "firstName" state
onChange={(e) => updateFirstName(e.currentTarget.value)}
value={firstName}
/>
</label>
<p>
Hello, <strong>{firstName}!</strong>
</p>
</main>
)
}
这里简单讲一下zustand useStore hook中的shallow
参数,它代表浅层比较,即只会比较数组或对象的引用是否相同,而不会比较数组或对象的内容是否相等,以减轻性能对消耗,但也可能造成不必要的错误。该hook默认进行深层比较,即递归比较对象的所有属性。
deeply nested object的状态更新
像这样的对象就属于deeply nested object:
type State = {
deep: {
nested: {
obj: { count: number }
}
}
}
原始更新方法是使用...扩展运算符
,zustand提供了一种方法叫immer
,可以用来更新嵌套值,也可以使用optics
、ramda
。