Created
March 1, 2022 13:04
-
-
Save tomiolah/6b823e4fdbf8cb4841eeb114bb415c7f to your computer and use it in GitHub Desktop.
Recoil effect, which persists + reads Recoil atom state to / from localForage (IndexedDB)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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