DEV Community

Anthony Humphreys
Anthony Humphreys

Posted on • Originally published at reacthooks.dev

useBrowserStorage

For day 3 of my #100DaysOfCode challenge I thought I would expand and polish a hook I previously wrote (adapted from several examples online such as this one) which wraps the useState hook and persists state in localStorage or sessionStorage depending on use case.

The hook conforms to a mix of the localStorage and useState API.

const [state, setState] = useBrowserStorage("key", "value", StorageType.LOCAL_STORAGE)
Enter fullscreen mode Exit fullscreen mode

This is so simple to use, virtually a drop in replacement for useState and gives you state persistance and restoration. You can use state as an ordinary state variable, and call setState with either a string or a function, just like the setter for useState.

That's it! Full hook code below, and published over at npm with the code available on GitHub

import { useState } from 'react';

enum StorageType {
  LOCAL_STORAGE = 'LOCAL_STORAGE',
  SESSION_STORAGE = 'SESSION_STORAGE',
}

export const useBrowserStorage = (
  key: string,
  initialValue: string,
  type: StorageType
) => {
  const storageProvider =
    type === StorageType.LOCAL_STORAGE
      ? window.localStorage
      : window.sessionStorage;

  const [storedValue, setStoredValue] = useState<string>(() => {
    try {
      const storedItem = storageProvider.getItem(key);
      return storedItem ? JSON.parse(storedItem) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value: string | Function) => {
    try {
      const valueToStore =
        value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      storageProvider.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
};
Enter fullscreen mode Exit fullscreen mode

UPDATE

This was originally published as 'useLocalStorage' - but then I realised using session storage in a hook called that wouldn't make much sense. Naming things is hard!

Top comments (0)