async-storage: AsyncStorage.getItem() doesn't seem to work


This issue was originally created by @mrded as facebook/react-native#18372.


When I try to set a value via AsyncStorage.getItem(), I cannot request it back.

Environment

Environment: OS: macOS High Sierra 10.13.3 Node: 9.8.0 Yarn: 1.5.1 npm: 5.6.0 Watchman: 4.9.0 Xcode: Xcode 9.2 Build version 9C40b Android Studio: Not Found

Packages: (wanted => installed) react: ^16.3.0-alpha.1 => 16.3.0-alpha.1 react-native: 0.54.0 => 0.54.0

Expected Behavior

await AsyncStorage.setItem('foo', 'bar');
await AsyncStorage.getItem('foo').then(console.log); // 'bar'
await AsyncStorage.getAllKeys().then(console.log); // ['foo']

Actual Behavior

await AsyncStorage.setItem('foo', 'bar');
await AsyncStorage.getItem('foo').then(console.log); // null
await AsyncStorage.getAllKeys().then(console.log); // []

Steps to Reproduce

import { AsyncStorage } from 'react-native';

it('should be able to request a value after it was set', async () => {
  await AsyncStorage.setItem('foo', 'bar');
  const output = await AsyncStorage.getItem('foo');

  expect(output).toBe('bar');
});

it('should be able to see a new key after a value was set', async () => {
  await AsyncStorage.setItem('foo', 'bar');
  const output = await AsyncStorage.getAllKeys();

  expect(output).toContain('foo');
});

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 19
  • Comments: 35 (11 by maintainers)

Most upvoted comments

@Krizzu - i still see a reload issue - after reload the storage is not set anymore and returns null. any suggestions?

We recently saw issues with this in our app on a large number of android devices when doing something very similar to the above in production but we had issues reproducing locally. Very happy to help do the work necessary to fix this. Would be great to use this thread to maybe identify what’s causing the issue and different approaches we could use to fix.

@royisch I believe that something in your implementation is causing to (maybe) override values in Async Storage (or calling .clear in startup.).

I’m closing this issue, if you’ll need more help, please open new issue with provided repro steps.

thanks.

yes. I set using asyncStorage.set, for testing purposes i verified that the data is persisted, so i fetch it back - all looks good. When i reload the same key i get null. In general for my use-case - you authenticate and go in. when you reload you see the login screen again.

My question is - should i revert to react-native implementation for now? as my application is waiting to be released.

Ah amazing! Had to patch a few packages we’re using that used the old version of AsyncStorage, but now that warning it gone and it seems to have solved the issue.

Thank you!

@jckw We are experiencing similar issue in our app. We haven’t been able to reproduce the error ourselves, but we have customers from time to time complaining they have to login again (meaning the token was lost). Telling them to reboot the device seems to fix the problem on future login. We tried using react-native-shared-preferences instead with no luck.

Investigated a bit more, and the issue isn’t async-storage issue. It was react-native-debugger that doesn’t instantly show the result when saving an item. I had to refresh the app to see the item in the debugger. Works as expected currently. Thanks and sorry for the confusion!

I’m still encountering this issue.

I set a token after logging in, and can access it after it’s been set:

async function setToken(token) {
  await AsyncStorage.setItem(AppConfig.TOKEN_STORAGE_KEY, token)
  
  const t = await AsyncStorage.getItem(AppConfig.TOKEN_STORAGE_KEY)
  console.log(t)
}

After reloading the app, await AsyncStorage.getItem(AppConfig.TOKEN_STORAGE_KEY) returns null.

Not using await in the setToken function also doesn’t help.

I’m using React Native v0.59.5 and @react-native-community/async-storage v1.3.3.

Hi @Krizzu i mean await asyncStorage.setItem. i will try to clear cache and report back

I have the same issue, but found a way to make it work with .then().

We have a separate helper class called StorageHelper that has some methods for getting and setting like:

// StorageHelper.js

async function set(key, value) {
  try {
    await AsyncStorage.setItem(key, JSON.stringify(value));
  } catch (error) {
    console.error(error);
    return false;
  }

  return true;
};

async function get(key) {
  try {
    const value = await AsyncStorage.getItem(key);

    return JSON.parse(value);
  } catch (error) {
    console.error(error);
    return null;
  }
};

...

setToken(token) {
    return set('token', token);
},

getToken() {
    return get('token');
},

...

These were working just fine by utilizing them like this: const token = await Storage.getToken(); and Storage.setToken(token);

Then, I added a new one. I followed the exact same patterns, just changing the name and all of a sudden this same way of getting the value for this token is returning either a Promise or null when I try: const token = await Storage.getToken();

The only way I was able to get the value for token and use it in my component was:

constructor(props) {
    super(props);

    this.state = {
      token: null,
    };
  }

  componentDidMount() {
    this.setTokenFromStorage();
  }

  setTokenFromStorage = () => {
    Storage.getToken().then((token) => {
      this.setState({ token });
    });
  }

Not as ideal, but hope it may help someone.