У меня есть компонент ниже, который использует хуки React:
import React, {useState} from 'react';
// import components
import TagManagementRow from './TagManagementRow';
const TagManagementList = (props) => {
const [tagData, setTagData] = useState(props.data);
const deleteAction = (id) => {
// Call to backend to delete tag
const currentData = [];
for( var i = 0; i <= tagData.length; i++){
if (i < tagData.length && tagData[i].id !== id) {
currentData.push(tagData[i]);
}
if (i === tagData.length) setTagData(currentData);
};
};
return (
<ul className = "tagManagement">
{tagData.map( (tag,i) => {
return <TagManagementRow name = {tag.name} key = {i} id = {tag.id} delete = {() => deleteAction(tag.id)} />
})}
</ul>
);
}
export default TagManagementList;
Он отображает 4 дочерних компонента TagManagementRow, каждый из которых имеет кнопку удаления. Когда я нажимаю кнопку удаления, все выглядит хорошо, если я выхожу из измененного состояния на консоль, однако в реальном браузере последний элемент в списке удаляется. Я чувствую, что это какая-то проблема рендеринга/времени, но я не могу понять это. Любая помощь от тех, кто лучше разбирается в крючках, будет принята с благодарностью.
Кстати, вот код компонента TagManagementRow:
import React, { useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const TagManagementRow = (props) => {
const [editTag, setEdit] = useState(false);
const [tagName, setTagName] = useState(props.name);
const [tempName, setTempName] = useState('');
const handleEdit = (e) => {
setTempName(e.target.value);
};
const switchToEdit = () => {
setEdit(!editTag);
}
const saveEdit = () => {
setTagName(tempName);
setTempName('');
switchToEdit();
}
return (
<li>
<span>
{tagName}
<FontAwesomeIcon icon = {["fas","pen"]} onClick = {switchToEdit} />
</span>
<span>
<FontAwesomeIcon icon = {["fas","trash-alt"]} onClick = {props.delete} />
</span>
</li>
);
}
export default TagManagementRow;
Вы могли бы так подумать, и именно так этот код ведет себя в другом месте нашего приложения.
Я предполагаю, что проблема заключается в том, что индекс используется в качестве ключа. У вас есть что-то, что вы можете использовать в качестве уникального идентификатора для каждого элемента данных (например, tag.id)?





Вместо обновления состояния внутри цикла вы можете использовать filter, чтобы отфильтровать объект с совпадающим идентификатором.
Также убедитесь, что вы используете tag.id как key вместо индекса массива, так как это изменится, когда вы удалите элемент.
const { useState } = React;
const TagManagementList = props => {
const [tagData, setTagData] = useState(props.data);
const deleteAction = id => {
setTagData(prevTagData => prevTagData.filter(tag => tag.id !== id));
};
return (
<ul className = "tagManagement">
{tagData.map((tag, i) => {
return (
<TagManagementRow
name = {tag.name}
key = {tag.id}
id = {tag.id}
delete = {() => deleteAction(tag.id)}
/>
);
})}
</ul>
);
};
const TagManagementRow = props => {
const [editTag, setEdit] = useState(false);
const [tagName, setTagName] = useState(props.name);
const [tempName, setTempName] = useState("");
const handleEdit = e => {
setTempName(e.target.value);
};
const switchToEdit = () => {
setEdit(!editTag);
};
const saveEdit = () => {
setTagName(tempName);
setTempName("");
switchToEdit();
};
return (
<li>
{tagName}
<button onClick = {props.delete}>Delete</button>
</li>
);
};
ReactDOM.render(
<TagManagementList data = {[{ id: 1, name: "foo" }, { id: 2, name: "bar" }]} />,
document.getElementById("root")
);<script src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root"></div>Спасибо, Толле, смена ключа, как вы рекомендовали, решила проблему. Так просто, настоящий момент ладони лица для меня. Спасибо за такое быстрое решение
Я не знаю, как ответить на это с помощью функциональных компонентов, но мне кажется, что componentDidUpdate решит эту проблему.