Ioana Surdu Bob
Ioana Surdu Bob

Reputation: 139

React Native - Async storage information is extracted after componentWillMount()

I am storing if a checkbox is checked or not using AsyncStorage. When I reload the app, I see from logs that inside the asynchronous variable the correct information is stored. But, it is loaded after componentWillMount. Because of that, the checkbox does not appear checked, as it should be.

I think a good workaround will be to change the checkbox properties inside the asynchronous function. Do you think that would be a good solution? Do you have other suggestions for showing the correct checkbox value?

My code:

constructor(props) {
    super(props)
    this.state = {isChecked: false}
    this.switchStatus = this.switchStatus.bind(this)
  }

  async getCache(key) {
    try {
      const status = await AsyncStorage.getItem(key);
      if (status == null)
        status = false
      console.log("my async status is " + status)
      return status
    } catch(error) {
      console.log("error", e)
    }
  }

  componentWillMount(){
    // key string depends on the object selected to be checked
    const key = "status_" + this.props.data.id.toString()
    this.getCache = this.getCache.bind(this)
    this.setState({isChecked: (this.getCache(key) == 'true')})
    console.log("my state is" + this.state.isChecked)
  }

  switchStatus () {
    const newStatus = this.state.isChecked == false ? true : false
    AsyncStorage.setItem("status_" + this.props.data.id.toString(), newStatus.toString());
    console.log("hi my status is " + newStatus)
    this.setState({isChecked: newStatus})
  }

  render({ data, onPress} = this.props) {
    const {id, title, checked} = data
    return (
      <ListItem button onPress={onPress}>
        <CheckBox
          style={{padding: 1}}
          onPress={(this.switchStatus}
          checked={this.state.isChecked}
        />
        <Body>
          <Text>{title}</Text>
        </Body>
        <Right>
          <Icon name="arrow-forward" />
        </Right>
      </ListItem>
    )
  }

There is no difference if I put everything in componentWillMount in the constructor.

Upvotes: 0

Views: 1873

Answers (3)

Ioana Surdu Bob
Ioana Surdu Bob

Reputation: 139

Thank you for your answers. I am pretty sure await will work too, but I solved the problem before getting an answer. What I did was set the state to false in the beginning, and then update it in getCache. This way, it will always be set after getting the information from the local phone storage.

async getCache(key) {
    try {
      let status = await AsyncStorage.getItem(key);
      if (status == null) {
        status = false
      }
      this.setState({ isChecked: (status == 'true') })
    } catch(e) {
      console.log("error", e);
    }
  }

Upvotes: 1

Mμ.
Mμ.

Reputation: 8542

The return value of an async function is a Promise object. So you have to use then to access the resolved value of getCache. Change your code to the following and it should work.

  componentWillMount(){
    // key string depends on the object selected to be checked
    const key = "status_" + this.props.data.id.toString();
    this.getCache(key).then(status => {
      this.setState({ isChecked: status === true });
    })
  }

Upvotes: 0

EnriqueDev
EnriqueDev

Reputation: 1247

you make use of the async - await, but you are not waiting for your method in componentWillMount(). Try this:

componentWillMount(){
    // key string depends on the object selected to be checked
    const key = "status_" + this.props.data.id.toString()
    this.getCache =  await this.getCache.bind(this)   // <-- Missed await
    this.setState({isChecked: (this.getCache(key) == 'true')})
    console.log("my state is" + this.state.isChecked)
  }

Upvotes: 0

Related Questions