When building web applications I often use this method to add local storage caching of my state.
Suppose we're starting with :
const [state, dispatch] = React.useReducer(
reducer,
initialState
)
as a first step we create a method that takes in a reducer and outputs another one, a higher-order function:
const withLocalStorageCache = reducer => { return (state, action) => {
const newState = reducer(state, action);
localStorage.setItem("my-state", JSON.stringify(newState));
return newState;
}};
and we wrap our reducer with it before passing the result to the useReducer
hook.
const [state, dispatch] = React.useReducer(
withCache(reducer),
initialState
)
And finally we replace initialState with the latest cached version of it :
const [state, dispatch] = React.useReducer(
withCache(reducer),
localStorage.getItem("my-state")
)
And that' s it !
One line of code modified and 5 new ones and our whole state is synced with localStorage.
We can, of course, limit our caching to only specific parts of the state instead of the whole state object. And limit our updates to the cache by action or state. But we'll leave that as an exercise to the user.
Complete demo
Top comments (3)
Very weird stuff ! It's not at all recommended to do that.
It's recommended to change the state key when changing the structure of the store (e.g. my-state-1, my-state-2)
This technique as is, requires the state to be serializable, to handle special cases you would need to add custom parsing and
stringifying
for non-serializable variables or simply ignore them when reading and writing to the the cache.Thanks for taking the time to write that !
The main reason I didn't go into it, is to keep the code under 5 lines π
I wanted the reader to quickly understand the idea of using HOFs with the reducer and build on it and experiment themselves.
Now they can also read/use this hook π