Skip to content

Instantly share code, notes, and snippets.

@Akurganow
Last active August 14, 2019 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Akurganow/942b4548ce03a3b20ab479053e6faada to your computer and use it in GitHub Desktop.
Save Akurganow/942b4548ce03a3b20ab479053e6faada to your computer and use it in GitHub Desktop.
usePersistedState
export interface Storage {
getItem: (key: string) => string | null
setItem: (key: string, value: string) => void
removeItem: (key: string) => void
}
const fallback: Storage = {
getItem: (key: string): string | null => {
console.log(`This is fallback key "${key}" cannot be readed`)
return null
},
setItem: (key: string, value: string): void => {
console.log(`This is fallback key "${key}" with value "${value}" cannot be writen`)
},
removeItem: (key: string): void => {
console.log(`This is fallback key "${key}" cannot be removed`)
},
}
export const localStorage = typeof window !== 'undefined' ? window.localStorage : fallback
import { useState, useEffect } from 'react'
import { localStorage, Storage } from './storages'
type usePersistedState<T> = [T, (value: T) => void]
export default function createPersistedState(
storageKey: string,
storage: Storage = localStorage
): [<T>(key: string, initialValue: T) => usePersistedState<T>, () => void] {
const safeStorageKey = `persist:state:${storageKey}`
const clear = (): void => {
storage.removeItem(safeStorageKey)
}
const usePersistedState = <T>(key: string, initialValue: T): usePersistedState<T> => {
const [state, setState] = useState<T>(initialValue)
const setPersistedState = (value: T): void => {
setState(value)
const persist = storage.getItem(safeStorageKey)
storage.setItem(
safeStorageKey,
JSON.stringify(
Object.assign(persist ? JSON.parse(persist) : {}, {
[key]: value,
})
)
)
}
useEffect((): void => {
const persist = storage.getItem(safeStorageKey)
if (persist) {
try {
const item = JSON.parse(persist)[key]
if (item) setState(item)
} catch (ignore) {} // eslint-disable-line no-empty
}
}, []) // eslint-disable-line react-hooks/exhaustive-deps
return [state, setPersistedState]
}
return [usePersistedState, clear]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment