-
-
Notifications
You must be signed in to change notification settings - Fork 103
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
react-native-async-storage support #87
Comments
We could potentially add an async-storage plugin. But mmkv should be much better for performance, especially because it loads synchronously so it's better for startup time. Are you unable to use mmkv or is there a reason you prefer not to use it? |
We have used mmkv before but it is not supported in the expo-managed workflow. To get started quickly we can use async-store initially and then can replace it with mmkv. I tried to do it myself but not working properly become of async behavior or I may be missing something. |
Oh, I thought it does work in expo, and a search makes it seem like it does? 🤷 If you're trying to write the plugin yourself, to get it to work with the async behavior you'd want to use the async I can add it to my todo list but I'm not sure when I can get to it. If a lot of others are needing it I can push it up the priority queue :). If you want to give it a stab yourself and submit a PR I can help with any questions or add some tweaks to finalize it, if you want? |
sure I will try and submit a PR thanks |
Here's what happens in expo:
|
MMKV is supported in managed expo, it just cannot be used with expo go. It can be added by installing and then building a custom dev client. I am using this in two managed apps and it works perfectly. Expo go is not intended as a development platform for your entire application. Support in Expo go should not be confused with managed workflow support. |
Not sure if it's still relevant but I build my own implem, hope it can help // ObservablePersistAsyncStorage.ts
import type { Change, ObservablePersistLocal, PersistMetadata } from '@legendapp/state';
import { setAtPath } from '@legendapp/state';
import AsyncStorage from '@react-native-async-storage/async-storage';
/**
* Can be replaced by MMKV official plugin (for synchronous persistency) as soon as you quit expo go
*/
const MetadataSuffix = '__m';
export class ObservablePersistLocalAsyncStorage implements ObservablePersistLocal {
private data: Record<string, any> = {};
// initialize() method allow us rehydrating data before calling getTable()
public async initialize() {
const tables = await AsyncStorage.getAllKeys();
const values = await AsyncStorage.multiGet(tables);
values.forEach(([table, value]) => {
this.data[table] = value ? JSON.parse(value) : undefined;
});
}
public getTable(table: string) {
if (this.data[table] === undefined) {
try {
// Unusual async process here - let's be vigilant 👀
(async () => {
const value = await AsyncStorage.getItem(table);
this.data[table] = value ? JSON.parse(value) : undefined;
})();
} catch {
console.error('[legend-state] ObservablePersistLocalAsyncStorage failed to parse', table);
}
}
return this.data[table] ?? {};
}
public getMetadata() {
return {};
}
public async get(table: string, id: string) {
if (this.data[table] === undefined) {
try {
const value = await AsyncStorage.getItem(table);
this.data[table] = value ? JSON.parse(value) : undefined;
return this.data[table]?.[id];
} catch {
console.error('[legend-state] ObservablePersistLocalAsyncStorage failed to parse', table);
}
}
}
public set(table: string, changes: Change[]): void {
if (!this.data[table]) {
this.data[table] = {};
}
for (let i = 0; i < changes.length; i++) {
const { path, valueAtPath, pathTypes } = changes[i];
this.data[table] = setAtPath(this.data[table], path as string[], pathTypes, valueAtPath);
}
this.save(table);
}
public updateMetadata(table: string, metadata: PersistMetadata) {
return this.setValue(table + MetadataSuffix, metadata);
}
public async deleteTable(table: string) {
await AsyncStorage.removeItem(table);
}
public deleteMetadata(table: string) {
this.deleteTable(table + MetadataSuffix);
}
// Private
private async setValue(table: string, value: any) {
this.data[table] = value;
await this.save(table);
}
private async save(table: string) {
const v = this.data[table];
if (v !== undefined && v !== null) {
await AsyncStorage.setItem(table, JSON.stringify(v));
} else {
await AsyncStorage.removeItem(table);
}
}
} // authState.ts
import { computed, observable } from '@legendapp/state';
import { persistObservable } from '@legendapp/state/persist';
import { ObservablePersistLocalAsyncStorage } from '@src/states/persistence/ObservablePersistAsyncStorage';
export type AuthState = { };
export const authState = observable<AuthState>({ });
persistObservable(authState, { local: 'authState', persistLocal: ObservablePersistLocalAsyncStorage }); |
Thank you @PierrePetiteau, that's very helpful! What does the |
hey so |
Oops, we added AsyncStorage support a while ago but I forgot to mention it in this issue. So I’m going to close this issue now :) See https://legendapp.com/open-source/state/v3/sync/persist-sync/#asyncstorage-rn |
Hi, I have been using it with expo managed project and loving it. but missing the async-storage support. How can we use it with async-storage?
The text was updated successfully, but these errors were encountered: