I needed to persist simple settings into localStorage in some react code, but the value of these settings were driven by a reducer. Composing a reducer and an effect hook seemed like a good case for my first custom react hook.
This is the first project that I've used hooks, and I've enjoyed how composable functional react has gotten out-of-the-box in the latest releases.
const usePersistedReducer = (key, reduce, initial) => {
// Setup the reducer, get initial from localStorage if available
const [value, setValue] = useReducer(
reduce,
localStorage.hasOwnProperty(key)
? JSON.parse(localStorage[key])
: initial
)
// Persist value when it changes
useEffect(() => { localStorage[key] = JSON.stringify(value) }, [key, value])
return [value, setValue]
}
// Usage examples:
// Reducer to toggle between showing or hiding selected tabs
const [filterTabs, toggleFilterTabs] = usePersistedReducer('filter-tabs', filterTabs => !filterTabs, false)
// Reducer that cycles through UI layout styles; horizontal, vertical, or block
const [layout, cycleLayout] = usePersistedReducer(
'layout',
layout => layouts[(layouts.indexOf(layout) + 1) % layouts.length],
layouts[0]
)