Zustand学习总结

· 560字 · 2分钟

Zustand 是一个小巧精美的状态管理库,可以很好的与 React 进行集成,并且提供中间件支持。 useSyncExternalStore 是 React 与 Zustand 沟通的桥梁。

关于 useSyncExternalStore 🔗

useSyncExternalStore 是一个订阅外部状态 Store 的 React hook,使用者需要提供一个订阅函数和一个获取 Store 数据的函数。 详细介绍可以查看官网

https://zh-hans.react.dev/reference/react/useSyncExternalStore

实现 Zustand 🔗

创建一个 Create State Store 函数,设置 Store 的初始 state 值并提供修改和获取 state 的函数。 为 useSyncExternalStore 提供 subscribe,subscribe 获取 listener。当组件状态更新,触发所有订阅 store 的组件渲染

// 创建一个Store
const createStore = (creatState) => {
  let state; // store 存储的值

  const listeners = new Set(); // 存储所有订阅 store 的 listener

  // 更新 state 的值
  function setState(partial) {
    const nextState = typeof partial === "function" ? partial(state) : partial;
    // 如果更新的值是一样的,不发生渲染
    if (Object.is(state, nextState)) {
      return;
    }
    state = Object.assign({}, state, nextState);
    // 触发listeners
    listeners.forEach((listener) => listeners());
  }

  // 获取状态
  function getState() {
    return this.state;
  }

  // 订阅 react 组件, react 会提供给 store一个listener
  // 当listener执行时,组件更新
  function subscribe(listener) {
    listeners.add(listener);

    return () => {
      listeners.delete(listener);
    };
  }

  state = creatState(); // 设置 state的值

  const api = { setState, getState, subscribe };

  return api;
};

创建 store 后,与 useSyncExternalStore 结合

const useStore = (api, selecter) => {
  return React.useSyncExternalStore(api.subscribe, selecter(api.getState()));
};

暴漏出 create 函数

const createImple = (createState) => {
  // 创建 store
  const api = createStore(createState);
  // selector获取执行状态
  const useBoundStore = (selector) => useStore(api, selector);

  return useBoundStore;
};

const create = (createState) => {
  createImple(createState);
};

export default create;

接下来就可以使用了

const createState = (set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
  updateBears: (newBears) => set({ bears: newBears }),
});

const useStore = create(createState);

function BearCounter() {
  const bears = useStore((state) => state.bears);
  return <h1>{bears} bears around here...</h1>;
}

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