Zustand入门

272 阅读2分钟

官网:docs.pmnd.rs/zustand/get…

安装

npm install zustand

特点

  1. 状态共享默认不需要 Provider。直接声明一个 hooks 式的 useStore 后就可以在不同组件中进行调用。
  2. 状态变更:函数可以直接写,不用区分同步或者异步,默认将所有的函数保持同一引用(不会造成额外的重复渲染)。get 对象,使得我们可以用 get 方法直接拿到当前 store 中最新的 state 快照
  3. 状态派生:用独立文件来管理派生状态(似useMemo)
  4. 性能优化:派生状态不会因数据不安话触发组件重新渲染
  5. 数据分形与状态组合:更容易拆分并组织代码,使用基于这种分形架构下的各种中间件(这点还没看懂)
  6. 多环境集成:不在 react 环境内的状态数据,如图表、画布、3D 场景直接拿值
  7. 测试方便:用test-library/react-hooks

使用

创建并绑定

import { create } from 'zustand'

//1、create a store
const useStore = create((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
}))

//2、bind your components
function BearCounter() {
  const bears = useStore((state) => state.bears)
  return <h1>{bears} around here...</h1>
}

function Controls() {
  const increasePopulation = useStore((state) => state.increasePopulation)
  return <button onClick={increasePopulation}>one up</button>
}

状态派生,入参为完整的store

export const nameSelector = (s) => return(s.name || '');
const name = useStore(nameSelector);
// 通过加入 isEqual 深比较,递归比较对象的所有属性和嵌套对象的属性,实现性能优化
const iconList = useStore(displayListSelector, isEqual);
// 通过加入 shallow 浅比较能力,只比较对象的顶层属性,实现「人工的依赖收集」,性能优化,等发现某些地方真的需要优化时,相应的套上 selector 就好;
const selector = (s: Store) => ({
    panelTabKey:s.panelTabKey,
    icon:s.icon
});
const PickerPanel = () => {
    const {panelTabKey, icon} = useStore(displayListSelector, shallow);
}

异步

const initialState = { designId: undefined, loading: false };
export const useStore = create((set, get) => ({ 
    ...initialState, 
    deprecateDraft: async () => {
        set({ loading: true }); 
        const res = await dispatch('/hitu/remote/ds/deprecate-draft', get().designId); 
        set({ loading: false }); 
        if (res) { message.success('草稿删除成功'); } 
        // 重新获取一遍数据 get().refetch(); 
    }, 
    refetch: () => {
        if (get().designId) {
            mutateKitchenSWR('/hitu/remote/ds/versions', get().designId); 
        }
    },
})

多环境集成

// 1. 创建Store
const useDogStore = create(() => ({ paw: true, snout: true, fur: true })) 
// 2. react 环境外直接拿值 
const paw = useDogStore.getState().paw 
// 3. 提供外部事件订阅 const unsub1 = useDogStore.subscribe(console.log) 
// 4. react 世界外更新值 
useDogStore.setState({ paw: false }) 
const Component = () => {
    // 5. 在 react 环境内使用 
    const paw = useDogStore((state) => state.paw) ...

组织架构

./store 
├── createStore.ts  // 负责书写创建 Store 的方法与 Action 方法;
├── selectors.ts    // 负责 Selector ——派生类选择器逻辑;
├── initialState.ts // 负责 State —— 添加状态类型与初始化状态值
└── index.ts

devtools

export type Store = State & Action; 
// 多一个函数执行,然后包裹 devtools 
export const createStore = ()=> create<Store>()(devtools((set, get) => ({ 
    ...initialState, 
    // ... action 
    selectIcon: (icon) => { 
        set({ icon, open: false, filterKeywords: undefined },false, "选择 Icon"); 
        get().onIconChange?.(icon); 
    }, 
}),{ name: 'IconPicker' }));

链接:
juejin.cn/post/717721…
juejin.cn/post/718246…