Async-storage: AsyncStorage on iOS is buggy

Created on 18 Apr 2019  ·  58Comments  ·  Source: react-native-async-storage/async-storage

Current behavior

Using @react-native-community/react-native-async-storage for Android works but for iOS is null when .getItem('@key', value) after .setItem('@key', value)

Expected behavior

AsyncStorage should get values from .setItem().
I had to revert to use react-native's built-in AsyncStorage in the meantime.

Repro steps

  • Install react-native-community/async-storage:"^1.3.3"
  • Launch react-native run ios
  • in the code, run await AsyncStorage.setItem('@key', 'value')
  • the same code with alert(await AsyncStorage.getItem('@key'))
  • value is null

Environment

  • Async Storage version: 1.3.3
  • React-Native version: 0.59.4
  • Platform tested: iOS and Android
  • Logs/Error that are relevant:
bug iOS

Most helpful comment

@muhammadn It seems to be a bug in the library, and I had the same issue. I have solved it downgrading to v1.2.4, I hope this solves your issue as well.

All 58 comments

Thanks for reporting this, @muhammadn. Your issue seems really odd to me as we have tests in place to prevent complete failures like this. Are you able to repro this in an entirely new app, e.g. in a newly ejected Expo app? Do you see anything in the logs at all?

@tido64 I will try to see the logs in Xcode with a fresh app. I found it is a really nasty bug where i thought it was a problem with my http library that fetches data with tokens stored in AsyncStorage..

I don't use expo though because of CI/CD reasons.

@muhammadn It seems to be a bug in the library, and I had the same issue. I have solved it downgrading to v1.2.4, I hope this solves your issue as well.

@muhammadn Tip: be sure to omit the caret to guarantee the downgrade. So in your package.json you should have:

"@react-native-community/async-storage": "1.2.4",

and you should NOT have:

"@react-native-community/async-storage": "^1.2.4",

@raynor85 Thanks! 🚀 , so you stick to only 1.2.4 and not upgrade to a patchlevel. Thanks for reminding me of that. I think i try 1.2.4 after this. Hopefully the bug in the recent release will get fixed soon.

@raynor85, @muhammadn: Did you also link with the library using react-native link or followed the Linking guide? A bug in 1.2.4 is making your app choose React Native's deprecated AsyncStorage over this library.

I did. My podfile has:

pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'

And you did a pod install or pod update RNCAsyncStorage afterwards? Sorry for all the questions but I personally learned the hard way that CocoaPods makes a copy of the Pod on install, so you always have to re-run update after a bump. Are you able to set a breakpoint in RNCAsyncStorage.m to see if the library gets called at all?

@tido64 I did run react-native link @react-native-community/async-storage. the odd thing was that it runs okay in android but not in ios.

@muhammadn Link just adds an entry to the Podfile. You still need to run pod install or pod update RNCAsyncStorage afterwards. On Android, link will add an entry to your Gradle build files and will be picked up correctly. CocoaPods is a third party dependency manager, and won't be picked up by Xcode automatically.

@tido64 I will try it out and see if it solves my problem.

@tido64 It is installed I confirm that. For me the issue is similar to the one @muhammadn has but it only occurs the first time you try to .setItem('@key', value). When I restart the app, and I execute .setItem('@key', value) again, .getItem('@key', value) works as expected. I suggest to uninstall the app to try to replicate the bug, so you guarantee that .setItem('@key', value) is always executed for the first time.

@tido64 weird. i tried to unlink and link again... no Podfile file in the ios directory

@muhammadn just to clarify, you need to have pod configured in your project, otherwise react-native link will write directly on your project.pbxproj. I suggest you to use the manual guide to install it if you don't have cocoapods installed https://github.com/react-native-community/react-native-async-storage/blob/master/docs/Linking.md#project-linking

@muhammadn You might have to run pod init (see also Linking for the specific steps).

@raynor85 Do you have specific steps to repro this? I tried in our test app but I can't see it. I manually deleted RCTAsyncLocalStorage_V1, and made sure that setItem is the very first call:

$ cat RCTAsyncLocalStorage_V1/manifest.json
{"random":"10"}

I can confirm i have same issue.
Was using version 1.3.4 and downgraded to version 1.2.4 and everything was working again.

@julianklumpers Do you have any repro steps? What issue you have on v1.3+ ?

I had just upgraded to RN 0.59.5 from 0.55.5, and hence migrated to using this library for AsyncStorage, directly to 1.3.4.

Just adding in to help debug the issue, I did not get any issue in the debug or production builds related to AsyncStorage.

I had then same issue with 1.3.3 and 1.3.4. then I have downgraded to 1.2.4 as mentioned in above comments, then everything works fine for me. we should find the bug.

This is starting to sound more like a build issue to me. As I mentioned above, 1.2.4 doesn't use this library's native modules. It's equivalent to not using this library at all. Would you mind trying some steps for us?

  1. Delete the node_modules folder(s) from your project
  2. Run yarn or npm install
  3. If you're using CocoaPods:

    1. Make sure your Podfile has this entry: pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'

    2. Make sure your Podfile does _not_ have an entry for react-native-async-storage.

    3. pod install

    4. pod update RNCAsyncStorage

  4. Open your Xcode project
  5. Press ⇧⌥⌘K to clean your build folder
  6. Build and run your project

Let us know how it goes, and please post any suspicious messages in the console that might help us debug this.

I was having similar issues. Also using CocoaPods.

After running pod update RNCAsyncStorage the issues were resolved 👍

same issue
i use 1.4.0

example

AsyncStorage.getItem('TEST_KEY')
        .then((result) => {
            if (result === 'TEST_DATA') {
                console.log(result)
            } else {
                console.log(result)
                AsyncStorage.setItem('TEST_KEY', 'TEST_DATA')
                    .then(() => {
                        console.log('setItem then')
                    })
                    .catch(
                        () => {
                            console.log('setItem catch')
                        }
                    )
            }
        })
        .catch(() => {
            console.log('catch')
        })

if I reload my app, getItem return null

  1. if you call getItem immediately after the setItem, then everything works

@Knjaz89 Can you try the steps I outlined a few posts above?

@Knjaz89 Can you try the steps I outlined a few posts above?

yes. i did it. same issue

@Knjaz89 Your example code is wrong - getItem does not accept string as a second argument.

In your case, there's no app crash (@RNC/AsyncStorage is null error), just wrong values saved/read, correct?

@Knjaz89 Your example code is wrong - getItem does not accept string as a second argument.

In your case, there's no app crash (@RNC/AsyncStorage is null error), just wrong values saved/read, correct?

Yep. its my implement. Get item 1 argument.AsyncStorage.getItem('TEST_KEY')
does not work

@Knjaz89 Your example code is wrong - getItem does not accept string as a second argument.

In your case, there's no app crash (@RNC/AsyncStorage is null error), just wrong values saved/read, correct?

I set the value, and later request it by hanging the getItem on the button, then everything works.
If you do not make a call by the button, it does not work.

So I've been running up against this issue lately as well, hopefully I can contribute meaningfully.
relevant package.json

    "@react-native-community/async-storage": "1.4.0",
    "react": "^16.8.6",
    "react-native": "^0.59.8",

podfile:

target 'APP-NAME-REMOVED' do
  rn_path = '../node_modules/react-native'

  pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec"
  pod 'React', path: rn_path, subspecs: [
    'Core',
    'RCTActionSheet',
    'RCTAnimation',
    'RCTGeolocation',
    'RCTImage',
    'RCTLinkingIOS',
    'RCTNetwork',
    'RCTSettings',
    'RCTText',
    'RCTVibration',
    'RCTWebSocket'
  ]
  pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'

pod install console log

Analyzing dependencies
Fetching podspec for `RNCAsyncStorage` from `../node_modules/@react-native-community/async-storage`
Fetching podspec for `React` from `../node_modules/react-native`
Fetching podspec for `yoga` from `../node_modules/react-native/ReactCommon/yoga/yoga.podspec`
Downloading dependencies
Using CocoaLumberjack (3.5.1)
Using RNCAsyncStorage (1.4.0)
Using React (0.59.8)
Using yoga (0.59.8.React)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete!

all JS imports (checked countless times)

import AsyncStorage from '@react-native-community/async-storage';

Of note: my app always shows the yellowbox warning Warning: Async Storage has been extracted from react-native ... despite checking every file ad nauseam for importing from the wrong package. I checked my node_modules to see if it was a dependent package usage, but that doesn't appear to be the case.
My use case:
user logs in to app.
Store auth token in await AsyncStorage.setItem('@app:auth', token);
Any other page, during any point after this while the app is live can do a await AsyncStorage.getItem('@app:auth'); and the token is returned successfully.
As soon as I bounce the app (force close it, dev tool reload) the await AsyncStorage.getItem('@app:auth'); returns null.

I've been using AsyncStorage in said app without issue for ~1.5 years. This has only become an issue very, very recently, but I'm not sure if it was when I switched to the community package or if I had seen symptoms before moving to this package.

@Metroninja Hey, thanks, that's very helpful. So it seems like everything is linked/used correctly at your end.

You can see yellow warning probably because of a dependency that still uses Async Storage from React Native.

Do you use redux-persist by any chance? Can you repro the same thing with fresh project (more or less your config) ?

thanks.

@Krizzu - I neglected to mention that, which is an important point. I do not use redux-persist. I'm currently rolling back async-storage to 1.2.4 to see if that resolves the issue like above, will post shortly my findings.

I can confirm rolling back to version 1.2.4 alleviates the problem ¯_(ツ)_/¯

@Metroninja (AFAIR) version 1.2.4 uses AsyncStorage from React Native directly, due to regression we found. So it's not really solving any issue.

If you remove RNC Async Storage do you still see yellow warning?

@Krizzu I don't want to sidetrack the issue with the yellowbox warning (as so often happens in github issues), I want to do my best to assist in tracking down the iOS persisting it's data issue! That said next when I fire up a debug build later I'll check.

as to v 1.2.4, the value for me was to see if the old package (since it was mentioned above that it used the old library directly) was the issue, or if there truly is a problem with the new library, and it appears there is something wrong here to cause this. It seems like asyncStorage is working just fine until the app reloads, after which time the data is dropped by the iOS app.

@Metroninja Right, thanks for help so far. I want to eliminate other possible causes. It'd be great to have a repo that can reflect the issue you're having. I launched Example and created a new project from init - AsyncStorage works fine for me, holding data after reload/app restart. Any idea how to reproduce your case?

thanks

I've spun up a small test project and have yet to reproduce the bug. I'm going to see what other factors here could cause it, if I can track down a direct repro I'll upload the repo here. Next areas I plan to look are with redux and/or react-navigation.

This is starting to sound more like a build issue to me. As I mentioned above, 1.2.4 doesn't use this library's native modules. It's equivalent to not using this library at all. Would you mind trying some steps for us?

  1. Delete the node_modules folder(s) from your project
  2. Run yarn or npm install
  3. If you're using CocoaPods:

    1. Make sure your Podfile has this entry: pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
    2. Make sure your Podfile does _not_ have an entry for react-native-async-storage.
    3. pod install
    4. pod update RNCAsyncStorage
  4. Open your Xcode project
  5. Press ⇧⌥⌘K to clean your build folder
  6. Build and run your project

Let us know how it goes, and please post any suspicious messages in the console that might help us debug this.

This really helped me. Now running Async Storage (community) v1.4.0.

Running 1.2.4 fixes the issue for us. Will this issue be addressed in future releases? Pretty serious bug imo.

Hi @Krizzu, I face same issue as @raynor85 also I use redux-persist. I get null value first time from AsyncStorage.getItem() then I reload the app and I get the expected value. I use AsyncStorage directly from react-native 57.8 inside App.js. Were you able to to get it work for you?

using 1.3.4 and 1.4.0 (and using react native debugger to log whats written to asyncstorage)

Not seeing keys being written to async storage with above versions. Without restarting app at all.

using 1.2.4 seeing keys written to asyncstorage correctly (assuming this is because its actually using the internal react-native asyncstorage because of the 1.2.4 regression issue)

Hey,

@franzwarning, to clarify:

  • v1.2.4 Does not use Community's Async Storage, but rather internal React Native version (this is fixed in 1.3.0)
  • v1.3.1 Fixed an iOS storage directory not being the same as internal RN used to have.

Meaning that it's best to use currently latest version (v1.4.0) or v1.3.1+.

@MalikHezretov So you say that you don't get proper values from RN's internal Async Storage?

@kbateman How do you check it? Any repro steps you could share?

Like I said before, it'd be a huge help if someone could provide a repo with a reproduced issue. I couldn't reproduce it myself so far.

Also, providing your Podfile (if using pods), libraries you use and repro steps would be greatly appreciated (so we can finally fix it).

thanks.

@Krizzu thanks for replying.

I get null instead of expected value first time. Then if I restart the app and go to that page second time I get the expected value.

@MalikHezretov right, could it be there some kind of race to save data? You can try to debug AsyncStorage which you have in node_modules (by putting, console logs in getItem/setItem methods, to see what's happening.

@Krizzu I believe data is being saved it is there in storage but The the problem is getting that item. I will debug it and see to be sure. Thanks.

@Krizzu The weird thing is, same code works fine on Android and not on iOS for first time only.

Hi,
I also have this issue. On loading I get error message "[@RNC/AsyncStorage]:NativeModule: AsyncStorage is null." And in code I only have "import AsyncStorage from '@react-native-community/async-storage';".

I have tried cleaning packager cache, removing node module and installing again. unlinking and linking.

dependencies:
"dependencies": { "@expo/samples": "2.1.1", "@react-native-community/async-storage": "1.4.1", "aws-amplify": "^1.1.27", "aws-amplify-react-native": "^2.1.11", "expo": "^32.0.0", "lodash.isequal": "^4.5.0", "native-base": "^2.12.1", "react": "16.5.0", "react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz", "react-native-button": "^2.4.0", "react-native-elements": "^1.1.0", "react-navigation": "^3.10.2", "reactotron-react-native": "^3.5.2" }

Running into the same issue on my side. After updating from 1.2.4 to 1.5.0 (or 1.4.x) I can add an item and read it immediately but a reload of the app or even running showAsyncStorageContentInDev() in the debugger will show the items were never persisted to storage.

I've tried re-installing, linking, unlinking but nothing seems to work. I've also manually linked but doesn't work either. Downgraded to 1.2.4 for now as that's the only version that seems to work.

@react-native-community/async-storage v1.6.1 same issue on ios, v1.2.4 work perfect

Overtime is to blame

Hi,I have the same issue Asyncstorage works fine on android but on ios getItem give null.
import {AsyncStorage} from 'react-native';

@muhammadn Tip: be sure to omit the caret to guarantee the downgrade. So in your package.json you should have:

"@react-native-community/async-storage": "1.2.4",

and you should _NOT_ have:

"@react-native-community/async-storage": "^1.2.4",

works like a charm !

@robleds Using 1.2.4 is like using AsyncStorage from react-native.

For iOS issue: I'd double check if one of your dependencies is still using AS from core - if it's the case, that means there's a race condition between Community's version and the core one.

If you're able to, change dependencies to use Community's AsyncStorage, otherwise, better fall back to react-native

Why 1.2.4 is working and latest version is buggy .. I'm using latest version and it acts weird on iOS (Android is fine). An error for example appeared sometimes “RCTAsyncLocalStorage_V1” couldn’t be removed.when I wanna clear the storage

This error sometimes appears and sometimes not which is strange.

I used this solution

const asyncStorageKeys = await AsyncStorage.getAllKeys();
if (asyncStorageKeys.length > 0) {
  AsyncStorage.clear();
}

any update?

I also would be interested, still encountering the IOS problem in 1.7.4

Have the same issue in 1.9.0

Please describe what issue you have in bit more details.

Was this page helpful?
0 / 5 - 0 ratings