Skip to content

Instantly share code, notes, and snippets.

@martinzuern
Last active May 14, 2020 21:30
Show Gist options
  • Save martinzuern/073f0a5b9ab8bf58207648857b53719f to your computer and use it in GitHub Desktop.
Save martinzuern/073f0a5b9ab8bf58207648857b53719f to your computer and use it in GitHub Desktop.
React useState paired with Window.localStorage
import React, { Dispatch, SetStateAction } from 'react';
import Log from './Log';
const isPlainObject = (obj: any) => Object.prototype.toString.call(obj) === '[object Object]';
const keyStr = (obj: any) => Object.keys(obj).sort().toString();
export function useStateWithLocalStorage<S = undefined>(
localStorageKey: string,
initialState: S | (() => S)
): [S, Dispatch<SetStateAction<S>>] {
let state: S | (() => S) = initialState;
// Restore from localStorage if possible
try {
const parsed = JSON.parse(localStorage.getItem(localStorageKey) || '');
if (parsed === null) throw new Error('Local storage is null');
// Basic type check
if (isPlainObject(parsed)) {
const schemaObj: S = initialState instanceof Function ? initialState() : initialState;
if (keyStr(schemaObj) !== keyStr(parsed)) throw new Error('Attributes do not match.');
}
state = parsed;
} catch (err) {
Log.info('Could not restore %s from local storage: %o', localStorageKey, err);
}
const [value, setValue] = React.useState<S>(state);
React.useEffect(() => {
localStorage.setItem(localStorageKey, JSON.stringify(value));
}, [value]);
return [value, setValue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment