如何为每个组件创建独立的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
相关产品推荐
相关产品推荐

