react-native-mmkv-storage: [Bug] Data missing from storage after app restart
Describe the bug
We received in the past few months many complaints about users being logged out from the app. After adding logging and investigating the incidents we found out that at random the getStringAsync
returns undefined
after the app is restarted.
If we restart the app again the getStringAsync
returns the expected value.
By restart I mean the app is closed by use with swipe up or is closed by to os and the user starts it again at a later time.
To Reproduce
Steps to reproduce the behavior:
- Initialize the storage with the following
this.storage = new MMKVStorage.Loader()
.withServiceName('com.test.app1.TestV1')
.withInstanceID('TestV1')
.withEncryption()
.initialize();
- Call
this.storage.setStringAsync('token', tokenValue);
on login to store the secret token - Call
this.storage.getStringAsync('token');
on each app start, if the call returns a value it means the user is logged in - On some restarts at random calling
this.storage.getStringAsync('token');
returns undefined after the value is set.
Expected behavior
After calling setStringAsync
, all the calls to getStringAsync
should return the value set.
Platform Information:
- OS: iOS
- React Native Version: 0.65.1
- Library Version v0.6.6
Additional context We are also curious if other people experience the same issue?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 2
- Comments: 128 (99 by maintainers)
We might have a potential fix to this issue. I will work on it asap.
Fix shipped in v0.7.0 Thanks @JoniVR for the insane debugging and finally fixing this too.
I’ve currently logged it like this in the latest test build (inside index.js):
In case anyone else wants to use it.
Now, let’s hope a user runs into it again, should generate an automatic crashlytics report. If not, a manual report will confirm through logging that the function works as intended but the issue might be elsewhere.
Hello, I have worked on a fix after the issue #207 was opened which brought me to a new and more predictable way to install JSI bindings. Basically the potential fix is taken from https://github.com/mrousavy/react-native-mmkv.
It’s not released yet but you should test this with the master branch:
After installation you will need to remove previous linking on Android.
MainApplication.java
: Remove the commented out lines as below.If you are using
reanimated@v2
then you should remove the modifiedCustomRNMMKVJSIModulePackage
inandroid/app/main/java/com/yourappid/
and remove any references to it inMainApplication.java
.Important Note: Once you get the iOS build running. Drop a comment here and let me know that storage is working in debug and you are able to read/write data. I don’t have a Mac with me at the moment so need a little help here.
@ammarahm-ed Done, let me know if anything else needs to be done 😃
@jaltin I am working on it.
Update: So far so good, no reports yet (neither manual nor automatic) 😄
@ammarahm-ed No problem, it’s easily misread and
dispatch_sync
is not used that often compared to the async variant. I deployed the possible fix about 48 hours ago, nothing reported so far… let’s hope it remains that way, usually takes a few days before they start popping up 🤞🏻I agree with you, will change it after confirming it solves the issue (or just whenever the fix is implemented in the library) 😀
@JoniVR
dispatch_async
will not work since it isasync
and the native call is synchronous so while you are trying to delay the return value, it will not be delayed actually. However doing the same insetItem
orgetItem
in JS will work since they areasync
.In native objc++ code, maybe we can use
std::thread thread_obj(lamda)
and then callthread_obj.join()
to make it wait for the result before returning value.I have been a bit busy. I plan to add a fix on Sunday which should work properly.
Hi @ammarahm-ed!
Just had a report where
getString
didn’t returnnull
butundefined
. See logs:@ammarahm-ed I did, they seem to all be printing the expected values:
I’ve set up automated crashlytics reporting for unexpected values again, let bug hunting season recommence! 😄
Most welcome. Do let me know if you face any other issues
@bombillazo Seems like your metro cache is old causing a problem when you upgrade loading old bundled js files. Restart metro bundler with cache reset:
If you don’t know how that works. Just remove
node_modules
folder and runnpm/yarn install
And now everything should work as expected.
@bombillazo Seems like everything is updated correctly. Try this:
@bombillazo
run
./gradlew clean
on/android
folder. Deletenode_modules
. Delete app from your phone. Then runyarn install
ornpm install
. Finally install the app again and everything should be good.Also you don’t need to run
npx mmkv link
on RN 0.67 and above.Also make sure to run
pod install
on iOS.Did this happen on iOS or Android?
Yes you don’t need this. However if you don’t remove it, everything should still work without changing anything. @bombillazo
@ammarahm-ed , I also tested it (for android, as that is where storage the issue was for my project) and the issue seems resolved as of the latest update the storage is working again and saving/retrieving my users. In the debug build and release build, both are working fine. Thanks for looking into it. really appreciate it.
OS: Android
@JoniVR just log
isLoaded
function’s result. It’s basically doing the same thing you were doing above manually.true
means that everything is working.Currently a project i’m working on has been having this issue also ( but for the android version only, ios is working fine ). As mentioned above by @ammarahm-ed i tried logging : Which returns undefined (both have been used in App.js)
console.log("storage initialized: ", global.getStringMMKV);
and also returns undefinedawait MMKV.setStringAsync("test", "some txt"); , const test = await MMKV.getStringAsync("isLoggedIn"); console.log('signin.js test: ', test);
Any additional info needed?
@JoniVR The very basic thing you should log:
This should return
[Function ...]
always. The most probable reason for this beingundefined
could be MMKV not registering at runtime. Add this and next time a user reports. Check to logs to see if storage was initialized or not.@JoniVR I will post here a list of things to Log. That will help in debugging.