#reactjs #react-hooks #use-state
#reactjs #реагирующие крючки #состояние использования
Вопрос:
В следующем примере я отображаю три элемента: 1, 2, 3. Я нажимаю на элемент 3, чтобы удалить его, однако на экране остаются элементы 2 и 3, а не только 1 и 2, поскольку элемент 3 должен был быть удален. Почему элемент 3 не удален?
Вот ссылка codesandbox, нажатие на 3 должно удалить ее: https://codesandbox.io/s/eager-currying-1bxnb?file=/src/App.js
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [items, setItems] = useState(data);
const onDelete = (id) => {
//LOGGING
console.log(`^^^^^^^^^^BEFORE DELETING^^^^^^^^^^^^^^^^`)
items.forEach( i => console.log(i.title))
console.log(`-----------------------------------------`)
//LOGIC
let filteredItems = items.filter((c) => c.id != id);
setItems([...filteredItems]);
//LOGGING
console.log(`^^^^^^^^^^AFTER DELETING^^^^^^^^^^^^^^^^`)
filteredItems.forEach( i => console.log(i.title))
console.log(`-----------------------------------------`)
};
return (
<div>
{items.map((i) => (
<Item id={i.id} title={i.title} onDelete={onDelete} />
))}
</div>
);
}
const data = [
{
id: 3,
uuid: "dbc74622-7002-41d2-9d89-e3d0d4558d25",
title: "Item 3"
},
{
id: 2,
uuid: "c7ac4c96-c1e0-45a4-a739-6ca4ad483b68",
title: "Item 2"
},
{
id: 1,
uuid: "48c90e0b-5b09-4583-8665-1f3d6f9df5f1",
title: "Item 1"
}
];
const Item = ({ id, title, onDelete }) => {
console.log(`Rendering Item ${title}`)
const [inputTitle, setTitle] = useState(title);
console.log(`Value set in useState ${inputTitle}`)
// ^ this is where the problem occurs even though I set "Item 2", this returs "Item 3"
return (
<div
onClick={() => {
onDelete(id);
}}
key={id}
>
<h3>{inputTitle}</h3>
</div>
);
};
Комментарии:
1. Не могли бы вы пояснить, почему порядок имеет значение? Если я удалил элемент из массива, он не должен присутствовать.
Ответ №1:
key
Prop должен идти на <Item>
компонент в вашем items.map()
обратном вызове, а не на <div>
элемент, у которого нет братьев и сестер. Это необходимо для того, чтобы React мог определить, какой Item
экземпляр в виртуальном DOM связан с каждым соответствующим элементом вашего items
массива.
В качестве примечания, вам не нужно распространяться filteredItems
при вызове setItems()
, поскольку items.filter()
метод уже возвращает новый экземпляр массива, поэтому setItems(filteredItems);
достаточно.