0

I currently learning react-native.

I am trying to stored a variable into asyncstrorage in scriptone.js and calling it in scripttwo.js

But i failed to stored the variable in scriptone.js

What i have import in scriptone.js:

import React, { Component, BackAndroid } from "react";
import { AsyncStorage } from 'AsyncStorage';
import { View, Text, StyleSheet, Button, Image, TouchableOpacity, TextInput, Alert} from "react-native";

This is part of my code in scriptone.js

class SettingScreen extends Component {
  state = {
      a: '70',
      b: '',
      c: '',
    }; 

onPressButton = () => {
      if (this.state.a == this.state.aa) {     
        this.setState({ b: this.state.a });
        this.storeData();
      }
       else {
        Alert("Try Again");
      }
    }

   storeData(){
        const {a} = this.state;
        let  mynum : a;
        AsyncStorage.setItem('array',mynum)
        Alert("Saved");
   }

...

The error display :

"undefined is not an object(evaluating '_AsyncStorage.AsyncStorage.setItem')

May I know what the problem? Thank you.

3
  • 1
    AsyncStorage is part of the core library, so you should import it from "react-native". Are you using some other library? Commented Jan 19, 2019 at 16:07
  • Whether you are using React-Native, facebook.github.io/react-native/docs/asyncstorage, or Expo, docs.expo.io/versions/latest/react-native/asyncstorage, the way to import AsyncStorage is the same import { AsyncStorage } from 'react-native' Perhaps if you shared your package.json and more of the code of your component then it may shed more light into why AsycnStorage is not working. Commented Jan 19, 2019 at 16:36
  • I have import the AsyncStorage from react-native. The error gone but i not sure is the variable stored in the asyncstorage. Btw, Thank you @JJJ Commented Jan 19, 2019 at 16:41

1 Answer 1

1

AsyncStorage

Usually to use AsyncStorage you first import it at the top of you file, the documentation says that you should import it as follows:

import { AsyncStorage } from 'react-native';

Which you can see here https://facebook.github.io/react-native/docs/asyncstorage

Obviously you should remove the previous import statement

import { AsyncStorage } from 'AsyncStorage'; 

as leaving it in will cause name conflicts.

Saving to AsyncStorage

Saving to AsyncStorage is an asynchronous task so you should use an async/await function that means you should update your storeData() function. You can see the documentation https://facebook.github.io/react-native/docs/asyncstorage for how you should do this.

storeData = async () => {
  const {a} = this.state;
  let  mynum = a;
  try {
    await AsyncStorage.setItem('array', mynum)
    Alert("Saved");
 } catch (err) {
    console.warn(err);
 } 
}

Setting state

Next it looks like you could be getting yourself into a race condition when you're setting the state. It takes time for setState to set the item to state. So when you call

this.setState({ b: this.state.a });

the state may not have actually been set by the time you call

this.storeData();

leading to the wrong value being stored in AsyncStorage.

To over come this there is a couple of ways you could handle this

  1. Use setState with a callback
  2. Pass the variable to store as a parameter to this.storeData()

Use setState with a callback

This article goes into quite some detail about using setState with a callback https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296 however you could refactor your onPressButton to something like this

onPressButton = () => {
  if (this.state.a == this.state.aa) {     
    this.setState({ b: this.state.a }, async () => { await this.storeData(); });
  } else {
    Alert("Try Again");
  }
}

This will guarantee that this.storeData() won't be run until the state has been updated.

Pass the variable to store as a parameter

This requires refactoring the storeData() function to take a parameter

storeData = async (mynum) => {
  try {
    await AsyncStorage.setItem('array',mynum)
    Alert("Saved");
 } catch (err) {
    console.warn(err);
 } 
}

Now to use this function we have to update your onPressButton, Notice that we pass the value that we want to store to storeData that means we no longer have to access it from state inside storeData

onPressButton = async () => {
  if (this.state.a == this.state.aa) {     
    this.setState({ b: this.state.a });
    await this.storeData(this.state.a);
  } else {
    Alert("Try Again");
  }
}

Retrieving from AsyncStorage

This is also an asynchronous task and requires an async/await. To get the string that you stored all you have to do is pass the correct key to the retrieveData function

retrieveData = async (key) => {
  try {
    const value = await AsyncStorage.getItem(key);
    if (value !== null) {
      // We have data!!
      console.log(value);
      // do something with the value
    }
   } catch (error) {
     // Error retrieving data
   }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Are there any specific reasons as to why the keys are set static? Even in the documentation, methods are making requests for a default key. The setter examples are done in a way they always either create or update data given a default key. See API documentation for more details. The application works by giving dynamic values as well, but I feel like I might be missing something.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.