English 中文(简体)
我可以使用一个在React 上下文中的 Zusstand 商店来创建该商店的多个实例吗?
原标题:Can I use a Zustand store inside a React context to create multiple instances of the store?
I m trying to create a post component where each post has its own state. The post component is really complex, so it s necessary to use the React context hook. import { createContext, useContext, PropsWithChildren } from "react"; import { create, StoreApi, UseBoundStore } from "zustand"; // Define the type of the context type LikesStore = { count: number; isLiked: boolean; initialize: (initialCount: number) => void; toggleLiked: () => void; }; // Define the type of the context type LikesContextType = UseBoundStore>; // Create the context const likesContext = createContext(undefined); // Create a hook to use the context const useLikesContext = () => { const context = useContext(likesContext); if (context === undefined) { throw new Error("useLikesContext must be used within a LikesProvider"); } return context; }; // Create a provider const LikesProvider = ({ children }: PropsWithChildren) => { // Zustand store const useLikesStore = create((set) => ({ count: 5, isLiked: false, initialize: (initialCount) => set({ count: initialCount }), toggleLiked: () => set((state) => ({ isLiked: !state.isLiked, count: state.isLiked ? state.count - 1 : state.count + 1, })), })); return ( {children} ); }; export { LikesProvider, useLikesContext }; Here s how it s used in different components within the Post component: function Counter() { const { count } = useLikesContext()(); return (
{count} likes
); } function LikeButton() { const { toggleLiked, isLiked } = useLikesContext()(); return ( ); } Is this approach appropriate, or should I revert to using useState or useReducer? Because I m leaning toward the Zustand approach because it suits my preferences better.
最佳回答
You can, but your LikesProvider will create a new store each time you render it. You should also consider using the useStore hook in useLikesContext, rather than just extracting the whole store. N.b. zustand/context` mentioned in @Oktay s answer is deprecated, and will be removed in v5 Adapting the documentation example: const LikesProvider = ({ children }: PropsWithChildren) => { const ref = useRef(create((set) => ({ count: 5, isLiked: false, initialize: (initialCount) => set({ count: initialCount }), toggleLiked: () => set((state) => ({ isLiked: !state.isLiked, count: state.isLiked ? state.count - 1 : state.count + 1, })), }))); return ( {children} ) } type UseLikesSelect = Selector extends (state: LikesStore) => infer R ? R : never const useLikesContext = any>(selector: Selector): UseLikesSelect => { const store = useContext(LikesContext) if (!store) { throw new Error( Missing LikesProvider ) } return useStore(store, selector) } Which you would then use in components like function Counter() { const count = useLikesContext(s => s.count); return (
{count} likes
); }
问题回答
Zustand has its own Provider functionality. zustand/context https://docs.pmnd.rs/zustand/previous-versions/zustand-v3-create-context From the example: import create from zustand import createContext from zustand/context const { Provider, useStore } = createContext() const createStore = () => create(...) const App = () => ( ... ) const Component = () => { const state = useStore() const slice = useStore(selector) ... If it does not fit you, you can use your implementation as well. With few changes. If you create a store inside a component, you have to memoize it, in order to create it only once and not on each render. const useLikesStore = useMemo(() => create(...), []) // create the store only once Better change your custom hook into this: const useLikesContext = (selector) => { // use a selector const useStore = useContext(likesContext); if (useStore === undefined) { throw new Error("useLikesContext must be used within a LikesProvider"); } return useStore(selector); // call it here, instead of returning the hook }; It is a hook, that returns another hook. This ensures that the returned hook will be called only at top level. const count = useLikesContext((store) => store.count); I don t see selectors in your example. If you don t use them, no need to use zustand, context will do the same thing.




相关问题
How to use one react app into another react app?

I have two react apps, parent app and child app. and child app have an hash router. I have build the child app using npm run build, It creates build folder. That build folder moved into inside the ...

how to get selected value in Ant Design

I want to print the selected value, and below is my option list: const vesselName = [ { value: 0 , label: ALBIDDA , }, { value: 1 , label: ALRUMEILA , }, { value: 2 ,...

How to add a <br> tag in reactjs between two strings?

I am using react. I want to add a line break <br> between strings No results and Please try another search term. . I have tried No results.<br>Please try another search term. but ...

热门标签