Search code examples
react-nativeasyncstoragererender

React native Unable to render the page with force update or set state


class Wait extends Component{

constructor(props) {
  super(props);
  this.state = { fetchingData: true, data: [], check: ''}
  this.forceUpdateHandler.bind(this);
  }

getData = async() => {
  try {
    data = await AsyncStorage.getItem('restaurants');
    if (data != null) {
      this.setState({fetchingData: false , data: JSON.parse(data)})
    }
  } catch(error){
     console.log(error)
  }
}

forceUpdateHandler(){
    this.forceUpdate();
};

componentDidMount(){
  this.getData();
}

renderRestaurant(){
  return this.state.data.map((item) => {
    return (
    <View style ={{marginTop: 20, backgroundColor: 'red', marginTop: 20 }}>
      <Text> {item.name} </Text>
      <Text> {item.time} </Text>
      <Text> {item.wait} </Text>
      <Text> {item.people} </Text>
      <Button title = 'cancel' onPress = { async () => {
        let data = await AsyncStorage.getItem('restaurants');
        let temp = JSON.parse(data)
        let i = -1
        temp.map((value, index) => {
          if (value.name == item.name){
            i = index;
          }
        })
        if (i > -1){
          temp.splice(i, 1)
          await AsyncStorage.setItem('restaurants', JSON.stringify(temp))
        }
        this.forceUpdateHandler()         // First way
        this.forceUpdate()                // Second way
        this.setState({check: 'checked'})   // Third way
      }
      }
      />
    </View>
  )
})
}

render(){
  const { navigate } = this.props.navigation;
  const { navigation } = this.props;

  return (
    <View style={{width:200, height:200, justifyContent:'center', alignItems:'center', }}>
          {this.state.fetchingData ? null : this.renderRestaurant()}
    </View>
  )
}
}

I am trying to make the page re-render each time after I click the button. Once click the button, it access the AsyncStorage and delete the corresponding element in the array, then it update the AsyncStorage with the new array and re-render the page.

I have tried the following:

1) call forUpdate directly after the update of the AsyncStorage
2) define the forceUpdateHandler function and bind it with this
3) call this.setState after the update of the AsyncStorage

But none of the above options re-renders the page. Can someone help to fix it? An example would be great! Thanks in advance.


Solution

  • The answer is simple. It doesn't re-render because it has nothing to re-render. It calls the render, check each component in the render if the data used to render it has changed and render them if needed. If you look at your code, you see that on the button press, you save in the async storage the new data. However, your rendering uses this.state.data to render the item. The problem is that you never update the state of your component with the new data.

    Sure, you do this.setState({check: 'checked'}), but nothing in the render is using it. So there's no point in updating the UI.

    An easy way to fix it would be to call this.getData() at the end of the button onPress. That way, you would update the data state which would update your UI.