Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save geekdaniels/dbf68f27af3b4be3f7cbe3b8a32acc0b to your computer and use it in GitHub Desktop.
Save geekdaniels/dbf68f27af3b4be3f7cbe3b8a32acc0b to your computer and use it in GitHub Desktop.
Recoil effect, which persists + reads Recoil atom state to / from localForage (IndexedDB)
import localforage from 'localforage';
import { AtomEffect, DefaultValue } from 'recoil';
/**
* Recoil module to persist state to storage
*/
export const recoilPersistLocalForage = ({ key = 'recoil-persist' }: { key?: string }): { persistAtom: AtomEffect<any> } => {
if (typeof window === 'undefined') {
return {
persistAtom: () => {},
}
}
const persistAtom: AtomEffect<any> = ({ onSet, node, trigger, setSelf }) => {
if (trigger === 'get') {
getState().then((state) => {
if (typeof state.then === 'function') {
state.then((s: any) => {
if (s.hasOwnProperty(node.key)) {
setSelf(s[node.key])
}
})
}
if (state.hasOwnProperty(node.key)) {
setSelf(state[node.key])
}
});
}
onSet(async (newValue) => {
const state = await getState()
if (typeof state.then === 'function') {
state.then((s: any) => updateState(newValue, s, node.key))
} else {
await updateState(newValue, state, node.key)
}
})
}
const updateState = async (newValue: any, state: any, key: string) => {
if (
newValue !== null &&
newValue !== undefined &&
newValue instanceof DefaultValue &&
state.hasOwnProperty(key)
) {
delete state[key]
} else {
state[key] = newValue
}
setState(state)
}
const getState = async () => {
const toParse = await localforage.getItem<any>(key)
if (toParse === null || toParse === undefined) {
return {}
}
if (typeof toParse === 'string') {
return parseState(toParse)
}
if (typeof toParse.then === 'function') {
return toParse.then(parseState)
}
return {}
}
const parseState = (state: string) => {
if (state === undefined) {
return {}
}
try {
return JSON.parse(state)
} catch (e) {
console.error(e)
return {}
}
}
const setState = async (state: any) => {
try {
await localforage.setItem(key, JSON.stringify(state))
} catch (e) {
console.error(e)
}
}
return { persistAtom }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment