我正在尝试学习新的 React 钩子。我写了一个简单的待办事项列表,用户可以输入输入以创建新的待办事项,然后单击待办事项将其删除。但是,删除待办事项后,它不会重新呈现。
这是我的代码
import React, { useState, Fragment } from "react";
const Todo = () => {
const [inputVal, setInput] = useState("");
const [list, setList] = useState([]);
const handleInput = e => {
setInput(e.target.value);
};
const handleClick = () => {
setList([...list, inputVal]);
setInput("");
};
const handleDelete = index => {
setList([...list.splice(index, 1)]);
console.log(list);
};
const renderList = () =>
list.map((item, index) => {
return (
<div key={index} onClick={() => handleDelete(index)}>
{item}
</div>
);
});
return (
<Fragment>
<div>
<input value={inputVal} onChange={handleInput} />
<button onClick={handleClick}>submit</button>
</div>
<ul>{renderList()}</ul>
</Fragment>
);
};
export default Todo;
您这里有两个问题。
array.splice
正在变异并返回已删除的项目。 当您运行时
setList([...list.splice(index, 1)]);
这会从对象list
中删除一个项目,然后调用setList([removed_item])
。
您可以将此行替换为
setList(list.slice(0, index).concat(list.slice(index + 1))
当前发生的情况是,您将状态设置为与之前相同的对象(但发生了变化(,因此它不会触发重新渲染。
- 您没有正确使用
key
属性。 您可以在此处阅读文档
如果项的顺序可能更改,我们不建议对键使用索引。这可能会对性能产生负面影响,并可能导致组件状态问题。
您的键应唯一标识待办事项列表的元素,而不引用列表本身。 项目中的文本是一个不错的选择,除了可能出现的非唯一性问题。
当你重新渲染待办事项列表时,React 会使用这些键来决定要重新渲染哪些子项。 如果使用索引作为键,然后删除索引 0 处的项,则不会告诉第 0 个子元素更新到新的第 0 个元素,因为它仍然获得相同的键。