#reactjs #react-context #react-state #react-state-management
Вопрос:
Я пытаюсь понять, как обновить массив, вложенный в контекст React. Ниже приведен контекст, с которым я работаю. Он состоит из «списков». Каждый список содержит массив «элементов».
import React, {useState, createContext} from 'react';
export const ListerContext = createContext();
export const ListerProvider = (props) => {
const [lists, setLists] = useState([
{
id: 1,
items: [{
itemid: 1,
text: 'Hello'
},
{
itemid: 2,
text: 'world'
}]
},
{
id: 2,
items: [{
itemid: 2,
text: 'Test'
}]
}
]);
return(
<ListerContext.Provider value={[lists, setLists]}>
{ props.children }
</ListerContext.Provider>
);
}
Я пытался изменить вложенные массивы, используя метод «setLists» ниже, но он не работает. Что я здесь делаю не так?
const removeListItem = (e) => {
setLists((prevList)=>{
for(var i = 0; i < prevList.length; i ){
if(prevList[i].id === parseInt(e.target.value[2])){
prevList[i].items = (prevList[i].items.filter(function(item) {
return item.itemid !== parseInt(e.target.value[0]);
}))
}
}
return prevList;
});
}
Комментарии:
1. Пожалуйста, никогда не публикуйте фотографии кода. Почтовый индекс в виде текста .
2. Подробнее о «…но это не работает» — как это не работает? Есть ли какая-то ошибка? Есть ли неожиданное поведение? Где вы вызываете removeListItem()? И т.д.
3. Прости! Вложенные массивы не меняются. Я могу обновить вложенные массивы в «PrevList», но когда обновленный предварительный список возвращается из метода setLists, изменения не отображаются в браузере.
4. Вам нужно вернуть совершенно новый массив. React знает об изменении только в том случае, если изменилась ссылка на массив. Клонируйте
prevList
сconst clone = [...prevList]
помощью, а затем мутируйте этот клон вместо этого и обязательно верните его. То же самое касается вложенных массивов или объектов. Реагируйте только тогда, когда меняются примитивы или ссылки.5. Я изменил заявление о возврате на:
return [...prevList];
и это сработало как заклинание. Спасибо!
Ответ №1:
Как отметил @zero298 в своем комментарии, вам нужно передать весь список в функцию обновления состояния setLists
. Вы инициализируете состояние и его функцию обновления с помощью «списка словарей», поэтому вам нужно продолжать относиться к нему как к таковому, вы не можете выборочно изменять несколько свойств внутри словаря или несколько элементов в списке без необходимости обновлять весь список.
Простая коррекция вашего кода будет заключаться в том, чтобы условно создать новую копию вашего списка с обновленными значениями, а затем установить этот список в качестве вашего нового состояния с помощью функции обновления состояния.
Ура!
Комментарии:
1. Похоже, ты прав. Я изменил оператор return для setLists на
return [...prevList];
, и браузер отображается правильно. Спасибо!