React Native State Management Question - когда загружается перехватчик useState?

У меня есть FlatList элементов, рядом с которым есть кнопка «удалить».

Когда я нажимаю кнопку удаления, я могу удалить элемент из серверной части, НО фактический элемент списка не удаляется из представления.

Я использую хуки useState, и, насколько я понимаю, компонент повторно отрисовывается после того, как происходит setState.

Функция setState используется для обновления состояния. Он принимает новое значение состояния и ставит в очередь повторную визуализацию компонента. https://reactjs.org/docs/hooks-reference.html

Что мне не хватает в том, как устанавливается состояние и рендеринг?

Я не хочу использовать прослушиватель useEffect по разным причинам. Я хочу, чтобы компонент повторно отображался при обновлении состояния местоположений .... что, я уверен, происходит с моими другими setStates ... не уверен, что я полностью пропускаю отметку о том, что делает setState, или если это что-то особенное о 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}/>

ОБНОВЛЕННЫЙ ЦИКЛ

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);
};

person Olivia    schedule 17.12.2019    source источник


Ответы (1)


Это сводится к изменению того же массива locations и повторному вызову setState с тем же массивом, что означает, что FlatList, который является чистым компонентом, не будет повторно визуализироваться, поскольку идентификатор locations не изменился. Вы можете сначала скопировать массив locations в newLocationsArray (аналогично newLocationNameArray), чтобы избежать этого.

      var newLocationsArray = locations.slice();
      var newLocationNameArray = locationsNames.slice();
person azundo    schedule 17.12.2019
comment
Я более или менее делаю это уже, кроме массива в цикле for. Я обновляю циклы for, чтобы отразить вновь созданный список, но состояние по-прежнему не отвечает. Не могли бы вы объяснить немного подробнее, почему установка состояния местоположений с новым массивом не работает? Я добавил в свой пост обновленный раздел. - person Olivia; 18.12.2019
comment
Нигде в removeLocationItemFromList не создаются какие-либо новые массивы - старые изменяются с помощью splice, а затем setState вызывается с измененным исходным массивом. Это означает, что когда FlatList проверяет, изменилось ли свойство data, это не так, поскольку это измененная копия того же массива. var spliceNewLocationArray =locations; будет иметь spliceNewLocationArray, указывающий на тот же массив, что и locations, он не копирует его и не создает новый массив. Для этого вам нужно использовать locations.slice() для копирования массива или var spliceNewLocationArray = [...locations]; в es6. - person azundo; 18.12.2019
comment
Ах я вижу. Спасибо, что сломали это. Все разрешено! - person Olivia; 18.12.2019