Add reducer equivalent of the API
AndrewIngram opened this issue · 3 comments
This looks great, at first glance the main thing lacking is an equivalent of useReducer for more complex state management. Any interest in extending it a bit?
Hmm... Interesting. Have any ideas? Seems like a different package, but would share many of the same functionality.
useState
is actually implemented in react using useReducer. The default reducer in this case is just (state, action) => typeof action === 'function' ? action(state) : action;
So it seems like it should be quite sufficient to add a parameter to usePersistedState
and implement a createPersistedReducer
(to keep a simple API and account for the fact that you fallback to the default state hooks).
It gets tricky, though, because usePersistedState
sets the state on storage change events and when another instance emits a setState event. In contrast, when using useReducer
, dispatch
never explicitly gets the state, so we can't really use useReducer
.
That being said, there's a neat package react-enhanced-reducer-hook that augments useReducer
in a clever way--by using setState
and implementing dispatch
itself. Looks like this library could use a similar strategy to implement a useReducer
variant.
A small preliminary sketch:
const createPersistedReducer = (
key,
provider = global.localStorage,
reducer = (state, action) => typeof action === 'function' ? action(state) : action,
) => {
if (provider) {
const storage = createStorage(provider);
return initialState => usePersistedReducer(reducer, initialState, key, storage);
}
return useReducer;
};
with usePersistedReducer
being:
// Omitting code that stays the same
const usePersistedReducer = (reducer, initialState, key, { get, set }) => {
// ...same ...
const dispatch = action => {
const next = reducer(state, action);
setState(next);
return action;
};
// ... same ...
return [state, dispatch];
};
Alternatively, depending on how much you want to condense down the code changes, I can see all of this extra functionality being added in with ~5 lines of changed code by adding a conditional or two to the existing functions.