mst-persist
mst-persist copied to clipboard
Persist changed value from `true` to `false`
Hi.
Environment info
React native info output:
System:
OS: Linux 5.3 Ubuntu 18.04.4 LTS (Bionic Beaver)
CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
Memory: 12.78 GB / 31.23 GB
Shell: 4.4.20 - /bin/bash
Binaries:
Node: 12.16.1 - /usr/bin/node
Yarn: 1.21.1 - /usr/bin/yarn
npm: 6.13.4 - /usr/bin/npm
npmPackages:
react: 16.9.0 => 16.9.0
react-native: 0.61.5 => 0.61.5
The problem is, when i persist RootStore with nested AuthStore, all my boolean value form AuthStore become from true
to false
.
When i just console.log its value, i have this behaviour
const { isLoading } = authStore;
console.log('isLoading => ', isLoading);
It is RootStore with nested AuthStore
import { types } from 'mobx-state-tree';
import { connectReduxDevtools } from 'mst-middlewares';
import AuthStore from './auth.store';
import { persist } from 'mst-persist';
import AsyncStorage from '@react-native-community/async-storage';
let store: any = null;
export default () => {
if (store) return store;
const RootStore = types
.model('RootStore', {
identifier: types.optional(types.identifier, 'RootStore'),
auth: AuthStore,
});
store = RootStore.create({
auth: {
isLoading: true,
},
});
/**
* Not working in debug mode
*/
persist('rootStore', store, {
storage: AsyncStorage,
}).then(() => {});
// @ts-ignore
if (__DEV__ && Boolean(window.navigator.userAgent)) {
connectReduxDevtools(require('remotedev'), store);
}
return store;
};
There is AuthStore
import { types } from 'mobx-state-tree';
const AuthStore = types
.model({
isLoading: types.optional(types.boolean, true),
});
export default AuthStore;
Can i persist only nested store?
How can i add isLoading
to whiteList
if it is nested store?
Thanks for narrowing this down to a more minimal example @YanisKondakov , was hard to read through before.
You still didn't quite provide an example of where this code is run:
const { isLoading } = authStore; console.log('isLoading => ', isLoading);
For it to log twice, it must've been run twice, and that's not in the code you've listed. authStore
also isn't defined anywhere.
Since you have isLoading
defaulted to true
, this shouldn't be affected by #5 , it should initialize an empty storage to true
as well.
It sounds like your problem is that isLoading
is changed to false
in your app somewhere, and then false
gets persisted. So when your app hydrates data from storage, it will hydrate to false
.
Can i persist only nested store?
Any persisted store will persist all its nested stores as well. But I'm struggling to fully understand what you meant here as there's some grammatical errors.
How can i add
isLoading
towhiteList
if it is nested store?
Did you mean to blacklist
? In either case, you've hit the mark here, there's no way to specifically whitelist
or blacklist
a nested property right now. You can blacklist auth
, but not auth.isLoading
.
This is a problem I'm looking to fix soon once I've got Transforms #16 merged in, likely using a similar dotted syntax as above. Deep blacklists are relatively easy to implement, but deep whitelists are more complex (especially if any conflict handling is added). This has popped up in my own usage as well, such as https://github.com/agilgur5/react-native-manga-reader-app/issues/27, so it's a known issue, but I never filed a formal issue for it. Will do that now. EDIT: see #27
There are some workarounds for this, but they're all a bit hacky without Transforms 😕 Like one is to manually set your storage to the default of true
. Sorry about that.
Side note:
isLoading: types.optional(types.boolean, true)
can just be simplified to:
isLoading: true
Per https://mobx-state-tree.js.org/concepts/trees#creating-models , they're equivalent.
Thank you @agilgur5 for the detailed answer. And sorry for my english.
The example of where this code is run
const { isLoading } = authStore;
console.log('isLoading => ', isLoading);
is
import React from 'react';
import createStore from './stores';
import { inject, observer, Provider } from 'mobx-react';
//This is a RootStore
const store = createStore();
const App = inject(({ authStore }) => ({ authStore }))(
observer(({ authStore }: any) => {
const { isLoading } = authStore;
console.log('isLoading => ', isLoading);
if (isLoading) {
return <SplashScreen />;
}
return (...);
}),
);
const AppProvider = () => (
<Provider rootStore={store} authStore={store.auth} profileStore={store.profile}>
<App />
</Provider>
);
export default AppProvider;
It sounds like your problem is that
isLoading
is changed tofalse
in your app somewhere, and thenfalse
gets persisted. So when your app hydrates data from storage, it will hydrate tofalse
.
As you can see, isLoading
is not changed to false
anywhere. And if i remove data hydrating, isLoading
log only once and it's value is true
.