I’m building a Configurator in R3F, with alot of options to customize. Currently i’m using a custom hook to share the states across my Components (Custumization.jsx, I cut some code for readability) :
I’m wrapping my App.jsx in this cutom hook, so i get access to all states from everywhere. When I’m logging “rerender” in one of the components of my Experience.jsx (it’s in the App.jsx) and i refresh the page i get 13 logs (Image below). I guess the problem is the custom hook but how can I get access to the states in a more efficient way?
Every tip would be helpful. Thanks
re-render in react isn’t harmful per-se, all it does is check for updates. but the reason is, like @mjurczyk said, context. it isn’t really meant to hold app state, it re-renders all context listeners and their sub trees on every change, which isn’t optimal.
worse, every time CustomizationProvider executes it triggers a fresh re-render of everything listening to CustomizationContext because you didn’t memoize the context value, which i would consider a bug. context shouldn’t be used w/o memoization.
however, if his log is in a single component that is used once, and the context is changed once, should we not still get 1 log? I mean, of course, unless he actually calls all 13 of those setXXX methods
yep, there’s definitively something over triggering it. in strict dev mode the component tree has to render twice because react stresses it out on purpose to flush out bugs and race conditions.
Is the problem, that the Experience uses so many states? And the initializing of those states triggers one rerender of the Experience? If yes, how can i make sure this does not happen (using default values maybe)?
Zustand can pick state, the point of it is that components can listen and react only to state they use and everything else stays put. But if you use it the same way as context, one major glob and every change triggers it and then you distribute it via prop drilling, that wouldn’t make sense.
Using it is good, but move state access to the components that rely on state
function Foo() {
const foo = useStore(state => state.foo)
const bar = useStore(state => state.bar)
That component listens to foo and bar, will only render it either of these changes unless it gets triggered by a parent rendering.
In your app there’s a part that triggers a state update 13 times, so you end up on the parent component 13 times. You have to figure out which does that.