I have the following code:
export function CurrentUserProvider({ children }) {
const [data, setData] = useState(undefined);
return (
<CurrentUserContext.Provider
value={{
data,
setData,
}}
>
{children}
</CurrentUserContext.Provider>
);
}
and I am doing the following to update the data:
const currentUser = useContext(CurrentUserContext);
currentUser.setData((prevData) => {
...prevData,
totalFollowers: prevData.totalFollowers + 1
});
Now I need to avoid unnecessary state updates. But I also need to be able to access the setData pure function.
My idea was to deep compare the new data object, updating my CurrentUserProvider:
export function CurrentUserProvider({ children }) {
const [data, _setData] = useState(undefined);
const setData = (newData) => {
if(!lodash.isEqual(newData, data)) {
setData(newData);
}
}
return (
<CurrentUserContext.Provider
value={{
data,
setData,
}}
>
{children}
</CurrentUserContext.Provider>
);
}
But... with this, I am not able to access prevData. Any ideas?
Make the equality check inside the setState callback, and if they are equal, return the previous state. According to the docs:
If your update function returns the exact same value as the current state, the subsequent rerender will be skipped completely.
export function CurrentUserProvider({ children }) {
const [data, _setData] = useState(undefined);
const setData = useCallback(newData => {
_setData(prevData => lodash.isEqual(newData, prevData)
? prevData
: { ...prevData, ...newData }
);
}, []);
return (
<CurrentUserContext.Provider
value={{
data,
setData,
}}
>
{children}
</CurrentUserContext.Provider>
);
}