Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with localForage #55

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

insaindesign
Copy link

localForage is incompatible with recoil-storage, return types are different.

localForage.getItem() returns Promise<null|string>. which makes getState return null, as there is no check for null from a promise.

localForage.setItem() returns Promise<string>. but recoil-storage doesn't care about that anyway, so doesn't have to enforce those types.

Making getState return a Promise always simplifies the code a lot, though that commit doesn't need to be part of this, but it better enforces the types.

src/index.ts Outdated
}

const parseState = (toParse: string) => {
const parseState = (toParse: string | null | undefined): PersistState => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should change this to PersistItemValue

@dende-h
Copy link

dende-h commented Apr 19, 2023

Hello.
Compatibility with localForage is what I am looking for. localStorage had capacity concerns.
With this code I was able to save and update to IndexedDB.
However, after the DB data is set on the first load, the update is set to the initial value in the onSet function.
Therefore, after the initial load, if the reload is performed again without updating the data, the DB data will be lost.
My atom code is as follows.

/* eslint-disable @typescript-eslint/no-empty-function /
/ eslint-disable @typescript-eslint/ban-ts-comment */
import { atom } from "recoil";
import { recoilPersist } from "../../components/util/customRecoilPersist";
import { draftObject } from "../selector/editorState";
import localforage from "localforage";

export type draftObjectArray = draftObject[];

localforage.config({
driver: localforage.INDEXEDDB,
name: "drafts",
version: 2,
storeName: "draftObject"
});

const { persistAtom } = recoilPersist({
key: "recoil-indexeddb",

storage: typeof window === "undefined" ? undefined : localforage
});

export const drafts = atom({
key: "drafts",
default: [],
effects_UNSTABLE: [persistAtom]
});

@dende-h
Copy link

dende-h commented Apr 20, 2023

Skipping onSet only on the first load as shown below worked as expected, but I am not very confident that it is a good method.
If you have a better solution, please let me know.

let firstFlug = false;

	const persistAtom: AtomEffect<any> = ({ onSet, node, trigger, setSelf }) => {
		if (trigger === "get") {
			getState().then((s) => {
				if (s.hasOwnProperty(node.key)) {
					setSelf(s[node.key]);
					firstFlug = true;
				} else {
					if (!firstFlug) firstFlug = true;
				}
			});
		}

		onSet((newValue, _, isReset) => {
			if (firstFlug) {
				if (isReset) {
					pendingChanges.reset[node.key] = true;
					delete pendingChanges.updates[node.key];
				} else {
					pendingChanges.updates[node.key] = newValue;
				}
				if (!pendingChanges.queue) {
					pendingChanges.queue = getState().then((state) => {
						if (JSON.stringify(state[node.key]) !== JSON.stringify(newValue)) {
							updateState(state, pendingChanges);
						}
						pendingChanges.queue = null;
						pendingChanges.reset = {};
						pendingChanges.updates = {};
					});
				}
			}
		});
	};

@polemius polemius force-pushed the master branch 2 times, most recently from 050c87f to 2f70d34 Compare May 17, 2023 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants