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]
)