If you declare an object within the context Provider value any context consumers will always re-render if the provider re-renders, because each time provider re-renders the object inside value
is re-declared.
return (
<Provider value={{ /* declared object */ }}>{children}</Provider>
);
value
PatternThis below is a good pattern, because store
will only change when setStore
has been called.
// ParentComponent.js
function ParentComponent() {
const [store, setStore] = useState({ bool: false });
return (
<Context.Provider value={store}>
<button onClick={() => setStore({ ...store, n: { bool: !store.n.bool } })}>
Switch Bool
</button>
<ContextConsumingComponent />
</Context.Provider>
);
}
// ContextConsumingComponent.js
function ContextConsumingComponent() {
const store = useContext(Context);
console.log('Will only run re-render if the `Switch Bool` button is clicked in parent.');
return <p>{JSON.stringify(context.bool)}</p>;
}
// Avoid re-renders if props haven't changed.
export default React.memo(ContextConsumingComponent);
value
PatternThis is a bad pattern, because <Provider value={{}} />
is listening for changes to the enclosing object, rather than the store
and setStore
references themselves. The reality is we only ever want to really listen to store
anyway.
// ParentComponent.js
function ParentComponent() {
const [store, setStore] = useState({ bool: false });
return (
<Context.Provider value={{ store, setStore }}>
<button onClick={() => setStore({ ...store, n: { bool: !store.n.bool } })}>
Switch Bool
</button>
<ContextConsumingComponent />
</Context.Provider>
);
}
I'd like to be be able to use setStore
in my context consuming components and I'd like to understand how other people approach this. I believe I have an option of two providers options but interested to see how others approach this and If I've missed any ±'s.
store
and dispatch
// Two Providers
function ParentComponent() {
const [store, setStore] = useState({ bool: false });
return (
<Store.Provider value={store}>
<Dispatch.Provider value={setStore}>
<button onClick={() => setStore({ ...store, n: { bool: !store.n.bool } })}>
Switch Bool
</button>
<ContextConsumingComponent />
</Dispatch.Provider>
</Store.Provider>
);
}
The answer to my question is likely useMemo
.
function App() {
const [store, setStore] = useState({ bool: false });
const memoized = useMemo(() => ([store, setStore]), [store, setStore]);
return (
<RCTX.Provider value={memoized}>
<button onClick={() => setStore({ bool: !store.bool })}>
Switch Bool
</button>
<SubComponent />
</RCTX.Provider>
);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.