Documentation incorrect: Usage with React Contexts #2633
-
Dear all, After reading a lot of blogposts on this, and the docs, the way I see it, there are two ways of combining Zustand with a react context:
There are many blogposts talking about this, and most notable discussion here is #730 There is also a section of the readme that briefly mentiones this, here https://github.com/pmndrs/zustand?tab=readme-ov-file#react-context Problems I'd like to fix:
Here is a copypaste of the Readme code, so that we can hopefully discuss it here: import { createContext, useContext } from 'react'
import { createStore, useStore } from 'zustand'
const store = createStore(...) // vanilla store without hooks
const StoreContext = createContext()
const App = () => (
<StoreContext.Provider value={store}>
...
</StoreContext.Provider>
)
const Component = () => {
const store = useContext(StoreContext)
const slice = useStore(store, selector)
... |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 6 replies
-
For reference, here is a full working example. The example shows a simple version of using a local Zustand store in a context (2), where if the Zustand element which renders the context is unmounted, a new state will be assigned on the very next mount. import { createContext, useContext } from "react";
import { createStore, useStore, type StoreApi } from "zustand";
type StoreState = { count: number; inc: () => void; dec: () => void; };
const StoreContext = createContext<StoreApi<StoreState>>(
undefined as unknown as StoreApi<StoreState>,
);
export function Zustand() {
const store = createStore<StoreState>((set, get) => ({
count: 0,
inc: () => set((state) => ({ count: state.count + 1 })),
dec: () => set((state) => ({ count: state.count - 1 })),
}));
return (
<div className="flex gap-4">
<button onClick={() => store.getState().dec()}>-</button>
<StoreContext.Provider value={store}>
<Child />
</StoreContext.Provider>
<button onClick={() => store.getState().inc()}>+</button>
</div>
);
}
function Child() {
const localStore = useContext(StoreContext);
const count = useStore(localStore, (state) => state.count);
return <div>Count: {count}</div>;
}
|
Beta Was this translation helpful? Give feedback.
-
@markomitranic in a nutshell zustand (react) and zustand/vanilla (pure javascript or vanilla javascript) |
Beta Was this translation helpful? Give feedback.
-
Hi, thanks for opening a discussion.
The incomplete code in readme.md is very intentional, but the feedback about needing brainpower is appreciated. The notation As we have a strong opinion about minimizing lines of readme.md, instead of changing code in readmd.md, we would like to create a separate md file in I wonder if @dbritto-dev 's rewrite covers it. Otherwise, a new PR is very welcome. |
Beta Was this translation helpful? Give feedback.
-
Can we introduce a more "built in" way of using zustand with react context like in this blog post? https://tkdodo.eu/blog/zustand-and-react-context
|
Beta Was this translation helpful? Give feedback.
-
After testing this a bit more, I’ve found that it isn’t possible to get a new zustand state each time the context mounts. (scenario 2) Yes, we do get a new state each time buuuut - As long as the store is declared inside of the component, it seems completely frozen in time - doesn’t cause rerenders. If the store is declared outside of the component, like in the guide, then it is global, and won’t reset on unmount. |
Beta Was this translation helpful? Give feedback.
Hi, thanks for opening a discussion.
The incomplete code in readme.md is very intentional, but the feedback about needing brainpower is appreciated. The notation
...
implies "incomplete". I wonder if it helps or not.As we have a strong opinion about minimizing lines of readme.md, instead of changing code in readmd.md, we would like to create a separate md file in
./docs
and only add a link in readme.md.I wonder if @dbritto-dev 's rewrite covers it. Otherwise, a new PR is very welcome.