create
方法可以帮助我们创建一个自定义 hook 用于状态管理
const useSomeStore = create(stateCreatorFn)
1type Create = {2<T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [], Mos>): UseBoundStore<Mutate<StoreApi<T>, Mos>>;3<T>(): <Mos extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [], Mos>) => UseBoundStore<Mutate<StoreApi<T>, Mos>>;4};
create 接收一个名为 stateCreatorFn
的函数作为参数。该函数的也接收三个参数,绝大多数情况下,我们只需要使用第一个参数即可
stateCreatorFn(setState, getState, store) {}
1export const useStore = create((set) => ({2x: 0,3y: 0,4update: (event: MouseEvent) => set({5x: event.pageX,6y: event.pageY7}),8}))
create 函数运行之后返回一个 react hooks,我们可以利用返回的 hook 访问 getState
setState
getInitialState
subscribe
四个方法。
例如,上一章的案例,我们可以利用 setState
进行改写来单独创建更新函数,注意观察 store.ts
10import { useEffect } from 'react'20import { useStore, update } from './store'3040export default function Counter() {50const { x, y } = useStore()6070useEffect(() => {80window.addEventListener('mousemove', update)90return () => {10window.removeEventListener('mousemove', update)11}12}, [])1314return (15<div className='text-center'>16鼠标当前位置17<div className='font-bold text-2xl mt-4'>{x}, {y}</div>18</div>19)20}
在组件中,我们可以直接通过解构的方式获取状态
const { x, y } = useStore()
这种方式的好处就是写起来比较简洁优雅。但是在 zustand 中,他会存在很大的性能风险,因为 store 中其他状态的更新,当前组件也会受到影响从而导致冗余的 re-render。如果你确保 store 的状态不会在别的组件中更新,那么就可以这样使用。
另外一种方式就是使用 selector
对状态进行选取,它可以有效的避免冗余的 re-render,坏处就是看上去不够优雅。许多开发者也因为这个原因而选择放弃 zustand
,这个主要看个人喜好
1const x = useStore(state => state.x)2const y = useStore(state => state.y)
完整的案例如下
10import { useEffect } from 'react'20import { useStore, update } from './store'3040export default function Counter() {50const x = useStore(state => state.x)60const y = useStore(state => state.y)7080useEffect(() => {90window.addEventListener('mousemove', update)10return () => {11window.removeEventListener('mousemove', update)12}13}, [])1415return (16<div className='text-center'>17鼠标当前位置18<div className='font-bold text-2xl mt-4'>{x}, {y}</div>19</div>20)21}