You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为每个组件创建独立的Zustand Store?

问题描述

我用极简Zustand Store实现了Cat组件:

import { shallow } from "zustand/shallow";
import { CatStoreSchema, useCatStore } from "./CatStore";

export const Cat = () => {
  const selector = (state: CatStoreSchema) => ({
    meows: state.meows,
    incrementMeows: state.incrementMeows,
  });

  const { meows, incrementMeows } = useCatStore(selector, shallow);
  
  return (
    <div>
      <span>Cat meowed {meows} times</span>
      <button onClick={incrementMeows}>Meow!</button> 
    </div>
  );
}

对应的Store代码:

import { create } from 'zustand';

export type CatStoreSchema = {
  meows: number;
  incrementMeows: () => void;
};

export const useCatStore = create<CatStoreSchema>((set, get) => ({
  meows: 0,
  incrementMeows: () => set(state => ({ meows: state.meows + 1 })),
}));

现在渲染多个Cat组件时,所有组件共享同一个Store,计数同步变化:

Cat meowed 15 times [Meow!]
Cat meowed 15 times [Meow!]

请问如何让每个Cat组件拥有独立的专属Store?


解决方案

方法一:Store工厂函数(简单直接)

不要直接创建全局Store,而是写一个返回新Store实例的工厂函数,让每个Cat组件自己生成专属Store。

修改Store文件

import { create } from 'zustand';

export type CatStoreSchema = {
  meows: number;
  incrementMeows: () => void;
};

// 工厂函数:每次调用都会创建一个全新的Store
export const createCatStore = () => {
  return create<CatStoreSchema>((set) => ({
    meows: 0,
    incrementMeows: () => set(state => ({ meows: state.meows + 1 })),
  }));
};

修改Cat组件

import { shallow } from "zustand/shallow";
import { createCatStore, CatStoreSchema } from "./CatStore";

export const Cat = () => {
  // 每个组件实例都会调用工厂函数,生成自己的Store
  const useCatStore = createCatStore();
  
  const selector = (state: CatStoreSchema) => ({
    meows: state.meows,
    incrementMeows: state.incrementMeows,
  });

  const { meows, incrementMeows } = useCatStore(selector, shallow);
  
  return (
    <div>
      <span>Cat meowed {meows} times</span>
      <button onClick={incrementMeows}>Meow!</button> 
    </div>
  );
}

这样每个Cat组件都有独立的Store,点击按钮只会改变自身的计数,互不干扰。

方法二:Context隔离(适合组件树共享局部Store)

如果需要在Cat的子组件中共享这个专属Store,用Context的方式更合适,能保证同一个组件树内的组件共用同一个Store,不同树的Store相互独立。

修改Store文件

import { create, createContext, useContext } from 'zustand';

export type CatStoreSchema = {
  meows: number;
  incrementMeows: () => void;
};

// 创建空的Context,用于传递Store实例
export const CatStoreContext = createContext<ReturnType<typeof createCatStore> | null>(null);

// 工厂函数:生成新Store
export const createCatStore = () => {
  return create<CatStoreSchema>((set) => ({
    meows: 0,
    incrementMeows: () => set(state => ({ meows: state.meows + 1 })),
  }));
};

// 自定义Hook,获取Context中的Store
export const useCatStore = () => {
  const store = useContext(CatStoreContext);
  if (!store) {
    throw new Error('useCatStore必须在CatStoreProvider内部使用');
  }
  return store;
};

创建带Provider的Cat组件

import { CatStoreContext, createCatStore } from './CatStore';
import { Cat } from './Cat';

export const CatWithProvider = () => {
  // 每个Provider实例创建自己的Store
  const catStore = createCatStore();
  
  return (
    <CatStoreContext.Provider value={catStore}>
      <Cat />
    </CatStoreContext.Provider>
  );
};

原Cat组件无需大幅修改

import { shallow } from "zustand/shallow";
import { useCatStore, CatStoreSchema } from "./CatStore";

export const Cat = () => {
  const selector = (state: CatStoreSchema) => ({
    meows: state.meows,
    incrementMeows: state.incrementMeows,
  });

  // 从Context中获取当前组件树的专属Store
  const { meows, incrementMeows } = useCatStore()(selector, shallow);
  
  return (
    <div>
      <span>Cat meowed {meows} times</span>
      <button onClick={incrementMeows}>Meow!</button> 
    </div>
  );
}

父组件中渲染多个独立Cat

export const App = () => {
  return (
    <div>
      <CatWithProvider />
      <CatWithProvider />
    </div>
  );
};

每个CatWithProvider实例都会生成独立的Store,它们的计数完全隔离。


内容的提问来源于stack exchange,提问作者ajthinking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:42:50