Search code examples
react-nativestatereact-hooksreact-state-managementreact-state

React Native State Management Question - when does useState hook load?


I have a FlatList of items that has a "remove" button next to it.

When I click the remove button, I am able to remove the item from the backend BUT the actual list item is not removed from the view.

I am using useState hooks and it was to my understanding that the component re-renders after setState happens.

The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component. https://reactjs.org/docs/hooks-reference.html

What am I missing with how state is set and rendering?

I don't want to use the useEffect listener for various reasons. I want the component to re-render when the locations state is updated....which I am pretty sure is happening with my other setStates....not sure if I am totally missing the mark on what setState has been doing or if it's something specific about setLocations().

    const [locations, setLocations] = useState(state.infoData.locations);
    const [locationsNames, setLocationsNames] = useState(state.infoData.names]);

    ...

    const removeLocationItemFromList = (item) => {
      var newLocationsArray = locations;
      var newLocationNameArray = locationsNames;
      for(l in locations){
        if(locations[l].name == item){
          newLocationsArray.splice(l, 1);
          newLocationNameArray.splice(l, 1);
        } else {
          console.log('false');
        }
      }
      setLocationsNames(newLocationNameArray); 
      setLocations(newLocationsArray);
    };

    ...

    <FlatList style={{borderColor: 'black', fontSize: 16}} 
      data={locationNames} 
      renderItem={({ item }) => 
          <LocationItem
            onRemove={() => removeLocationItemFromList(item)}
            title={item}/> } 
      keyExtractor={item => item}/>

UPDATED LOOP

const removeLocationItemFromList = (item) => {
  var spliceNewLocationArray =locations;
  var spliceNewLocationNameArray = locationsNames;
  for(f in spliceNewLocationArray){
    if(spliceNewLocationArray[f].name == item){
      spliceNewLocationArray.splice(f, 1);
    } else {
      console.log('false');
    }
  }
  for(f in spliceNewLocationNameArray){
    if(spliceNewLocationNameArray[f] == item){
      spliceNewLocationNameArray.splice(f, 1);
    } else {
      console.log('false');
    }
  }
  var thirdTimesACharmName = spliceNewLocationNameArray;
  var thirdTimesACharmLoc = spliceNewLocationArray;
  console.log('thirdTimesACharmName:: ' + thirdTimesACharmName + ', thirdTimesACharmLoc::: ' + JSON.stringify(thirdTimesACharmLoc)); // I can see from this log that the data is correct
  setLocationsNames(thirdTimesACharmName); 
  setLocations(thirdTimesACharmLoc);
};

Solution

  • This comes down to mutating the same locations array and calling setState with the same array again, which means that the FlatList which is a pure component will not re-render since the identity of locations has not changed. You could copy the locations array to newLocationsArray first (similarly with the newLocationNameArray) to avoid this.

          var newLocationsArray = locations.slice();
          var newLocationNameArray = locationsNames.slice();