#623 useLocalStorage

medium
react
hooks
browser api
storage

Implement a custom React hook useLocalStorage(key, initialValue) that works like useState, but keeps the value saved in localStorage so it survives a page reload.

const [value, setValue, remove] = useLocalStorage("theme", "light");

It returns a tuple:

  • value: the current value.
  • setValue(next): sets a new value and saves it. Like useState, next can be a value or an updater function (prev) => next.
  • remove(): deletes the key from localStorage and resets value back to the initial value.

Requirements:

  • On first render, read the stored value for key. If nothing is stored, use initialValue. initialValue can also be a function, which is only called when it is needed (like the lazy initializer of useState).
  • Values are saved with JSON.stringify and read with JSON.parse, so numbers, booleans, arrays and objects round-trip correctly. If the stored data is not valid JSON, fall back to initialValue instead of crashing.
  • Calling setValue several times in the same event handler with updater functions must apply every update in order.
  • setValue and remove must keep the same identity across renders.
  • When another browser tab changes or removes the same key, the hook should update to match. Hint: the storage event fires on window in the other tabs. A removed key (newValue === null) resets to initialValue. Events for other keys are ignored.
  • If key changes, the hook reads and writes the new key from then on.

Example

function ThemeToggle() {
  const [theme, setTheme, resetTheme] = useLocalStorage("theme", "light");

  return (
    <>
      <p>Current theme: {theme}</p>
      <button onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}>
        Toggle
      </button>
      <button onClick={resetTheme}>Reset</button>
    </>
  );
}

Reload the page and the theme you picked is still there. Open the page in two tabs and toggling in one updates the other.