Search code examples
react-nativeasyncstorage

Failed in retrieve data from AsyncStorage


I am a beginner at react-native. I trying to retrieve data that stored from screen1.js in Screen2.js but I failed.

I have import Asyncstorage from react-native for both .js

This how I store variable from screenone.js :

class screenone extends Component {
  state = {
      oldpin: '000000',
      newpin: '',
      secpin: '',
     };

  onPressButton = () => {
      if (this.state.newpin == this.state.secpin) {
        this.setState(
            { oldpin: this.state.newpin },
             async() => await this.storeData());
      }
       else {
        ToastAndroid.show("Password Unmatched", ToastAndroid.SHORT);
      }
    }

   storeData = async () =>{
        const {oldpin} = this.state;
        let  pin : oldpin;
        try{
            await AsyncStorage.setItem('mypin',pin);
            ToastAndroid.show("Password Changed", ToastAndroid.SHORT);
        }
        catch (err){
            console.warn(err)
        }}
....

This is how I trying to retrieve data in screentwo.js:

class screentwo extends Component {
  constructor(props) {
super(props);
this.onComplete = this.onComplete.bind(this);
this.state = {
  pin: ''
};
}

retrieveData = async (mypin) => {
  try {
    let value = await AsyncStorage.getItem(mypin);
    if (value !== null) {
      console.log(value);
      this.setState({
      pin: value})
    }
   } catch (error) {
      console.warn(err)
   }
}

onComplete(inputtedPin, clear) {
  retrieveData();
  if (inputtedPin !== this.state.pin) {
    ToastAndroid.show("Incorrect Pin", ToastAndroid.SHORT);
    clear();
  } else {
    ToastAndroid.show("Pin is correct", ToastAndroid.SHORT);
    clear();
    this.props.navigation.navigate("Dashboard");
  }}
  ....

Error:

Reference Error: ReferenceError:Can't find variable:retrieveData

Am I using the right way to stored and retrieve data? Any suggestion?

Thank you.


Solution

  • There are a couple of issues that I can see with your code.

    Firstly the retrieveData() function. It is asynchronous and should be called with await also you are getting the error: Reference Error: ReferenceError:Can't find variable:retrieveData because you haven't used this

    So ideally you should call it await this.retrieveData();

    There are a few more issues with this function. You use the parameter mypin but don't seem to pass any parameter to the function when you call it. Fixing this issue you should call retreiveData() like this:

    await this.retrieveData('mypin');

    Or you could remove passing the paramater altogether, which I will show how to do in my refactor below.

    Finally you call retreiveData every time you check the inputtedPin this isn't that efficient, it is asynchronous so it may take some time, and secondly it also takes time for the setState function to complete, which means that the state may not have updated in time when you go to check it against the inputtedPin, meaning that you are checking the inputtedPin against the wrong value.

    Code Refactor

    This is how I would refactor your component.

    1. Refactor retrieveData so that it no longer takes a parameter and the key is hardcoded in the .getItem
    2. In the componentDidMount get the value of the pin from AsyncStorage and save it to state.
    3. Remove the retrieveData call from onComplete

    Here is the refactor

    retrieveData = async () => { // parameter have been removed
      try {
        let value = await AsyncStorage.getItem('mypin'); // notice I am now passing the key as a string not as a parameter
        if (value !== null) {
          console.log(value);
          this.setState({ pin: value })
        }
       } catch (error) {
          console.warn(err)
       }
    }
    
    // here we call the refactored retrievedData which will set the state. 
    async componentDidMount () {
      await this.retrieveData();
    }
    
    onComplete(inputtedPin, clear) {
      // we remove the call to retrieveData as we have already gotten the pin in the componentDidMount
      if (inputtedPin !== this.state.pin) {
        ToastAndroid.show("Incorrect Pin", ToastAndroid.SHORT);
        clear();
      } else {
        ToastAndroid.show("Pin is correct", ToastAndroid.SHORT);
        clear();
        this.props.navigation.navigate("Dashboard");
      }
    }