AsyncStorage from @RNC?

The Expo docs for AsyncStorage (https://docs.expo.io/versions/latest/sdk/async-storage/) instruct to use expo install @react-native-community/async-storage, but I’m getting an error when building my app:

Error: [@RNC/AsyncStorage]: NativeModule: AsyncStorage is null

AsyncStorage works as intended when using expo start, but not after building.

Looking at previous posts this seems to be a problem with Expo not supporting @react-native-community/async-storage, and that I should import AsyncStorage from react-native.

Is this an error with the Expo docs, or is this caused by something else? I am using SDK 39.

I’ve just written a simple app that fetches from/writes to AsyncStorage. It works in development and it also works after building a standalone APK. This is of course also SDK 39.

Just to make sure, are you importing AsyncStorage from @react-native-community/async-storage or react-native (deprecated)?

Importing from react-native works without errors for me, but importing from @react-native-community/async-storage causes the error after installing the built .apk.

I imported from @react-native-async-storage/async-storage. I had no problem installing/running the built APK on my phone.

This was the test app:

import { StatusBar } from "expo-status-bar";
import React, { useEffect, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";

function storeData(value) {
  AsyncStorage.setItem("@storage_Key", value)
    .then(() => {
      console.log("Stored value", value);
    })
    .catch((e) => {
      alert("Error saving to AsyncStorage:" + JSON.stringify(e));
    });
}

function getData(setData) {
  AsyncStorage.getItem("@storage_Key")
    .then((value) => {
      console.log("Got value", value);
      setData(value);
    })
    .catch((e) => {
      console.log("Error reading from AsyncStorage: " + JSON.stringify(e));
    });
}

export default function App() {
  const [data, setData] = useState("initial");
  const [stored, setStored] = useState("");

  useEffect(() => {
    getData(setData);
  }, []);

  useEffect(() => {
    const timer = setTimeout(() => {
      const value = JSON.stringify(new Date());
      storeData(value);
      setStored(value);
    }, 3000);
    return () => clearTimeout(timer);
  }, []);

  return (
    <View style={styles.container}>
      <Text>Stored: {stored}</Text>
      <Text>Fetched: {data}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

package.json:

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@react-native-async-storage/async-storage": "^1.13.2",
    "expo": "~39.0.2",
    "expo-status-bar": "~1.0.2",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-39.0.4.tar.gz",
    "react-native-web": "~0.13.12"
  },
  "devDependencies": {
    "@babel/core": "~7.9.0"
  },
  "private": true
}

Eu consegui resolver indo na pasta “@react-native-async-storage/async-storage”/async-storage/src/AsyncStorage.native.js trocando o import que antes estava assim import RCTAsyncStorage from ‘./RCTAsyncStorage’ para import RCTAsyncStorage from ‘./RCTAsyncStorage.expo’;

1 Like

I also had the same experience as @wodin of it working during my initial testing.

But it seems upgrading expo has broken it and i can’t get it back.

Same with SDK40, fixed as @lucasrobert123 said :

Expo CLI 4.0.16 environment info:
    System:
      OS: macOS 10.15.7
      Shell: 5.7.1 - /bin/zsh
    Binaries:
      Node: 12.13.1 - /usr/local/bin/node
      Yarn: 1.22.5 - /usr/local/bin/yarn
      npm: 3.10.10 - /usr/local/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    Managers:
      CocoaPods: 1.9.3 - /usr/local/bin/pod
    SDKs:
      iOS SDK:
        Platforms: iOS 14.1, DriverKit 19.0, macOS 10.15, tvOS 14.0, watchOS 7.0
      Android SDK:
        API Levels: 23, 25, 26, 27, 28, 29
        Build Tools: 28.0.3, 29.0.2, 30.0.2
        System Images: android-25 | Google Play Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom_64, android-29 | Google APIs Intel x86 Atom
    IDEs:
      Android Studio: 3.6 AI-192.7142.36.36.6392135
      Xcode: 12.1/12A7403 - /usr/bin/xcodebuild
    npmPackages:
      expo: ~40.0.0 => 40.0.0
      react: 16.13.1 => 16.13.1
      react-dom: 16.13.1 => 16.13.1
      react-native: https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz => 0.63.2
      react-native-web: ~0.13.12 => 0.13.18
    npmGlobalPackages:
      expo-cli: 4.0.16
    Expo Workflow: managed

In node_modules/@react-native-async-storage/async-storage”/async-storage/src/AsyncStorage.native.js,
replace import RCTAsyncStorage from ‘./RCTAsyncStorage’ by import RCTAsyncStorage from ‘./RCTAsyncStorage.expo’;

2 Likes

Pode estar dando erro no metro.config.js se vc tiver tb. No meu caso aconteceu. Ai fiz como ducumentado no final do blog https://blog.expo.io/expo-sdk-40-is-now-available-d4d73e67da33
onde ensina dar o upgrade

@lucasrobert123 can you please post in English, I don’t understand Portuguese neither google translate … :wink:

I gather he’s saying that the problem could be with metro.config.js and that he fixed it by following the upgrade instructions at the end of the blog post.

So I suggest you double check that you’ve handled any breaking changes (check the blog post and the changelog.)

If that doesn’t fix it, you might try creating a new project with expo init and then compare all of the config files between the new project and the real project to see what might be different. If that doesn’t help, try creating a new project, install all the dependencies, copy all of the code/assets to the new project and see if it works then.

Same issue here and got it fixed, thanks. Using @expo/metro-config instead of the metro-config package in the metro.config.js file did the trick.

1 Like

@jgoss When I do this, I get

The “path” argument must be of type string. Received undefined

when trying to expo start.
For some reason, if I replace metro-config with @expo/metro-config, I can’t even run the app.
Any ideas?

Portuguese is highly adopted and very well documented! :wink: