reactjs - 通过数组索引从基于数组的状态中删除是否安全?
问题描述
我刚开始使用 React,我想知道通过数组索引删除是否安全,或者这是否会导致某种竞争条件/时间问题。作为一个具体的例子,让我们考虑一个有 3 行的表,每行都有一个删除按钮:
所以我的状态包含:
first row (index 0)
second row (index 1)
third row (index 2)
现在用户删除了第二行,给我们留下了这个数组内容:
first row (index 0)
third row (now index 1 instead of 2)
接下来,用户在组件重新渲染之前单击第三行,因此第三行的删除按钮仍然引用索引 2 而不是已经索引 1。因此splice(index, 2)
执行导致错误,因为索引 2 不再存在。
如果用户快速点击删除按钮,这在 React 中理论上是可能的吗?
示例代码 / Codesandbox
这是一些具体的代码示例,也可以在我的 Github 存储库中找到,尤其是在Codesandbox
App.tsx(相关代码摘录)
<MyTable
initialRows={[
{ id: 101, content: 'first row' },
{ id: 102, content: 'second row' },
{ id: 103, content: 'third row' }
]}
/>
MyTable.tsx(相关代码摘录)
import { FC, useState } from 'react';
interface Row {
id: number;
content: string;
}
interface Props {
initialRows: Row[];
}
export const MyTable: FC<Props> = function ({ initialRows }) {
const [rows, setRows] = useState(initialRows);
return (
<table>
<tbody>
{rows.map((row, index) => (
<tr key={`id${row.id}`}>
<td>{row.content}</td>
<td>
<button
type="button"
onClick={() => {
const newRows = [...rows];
newRows.splice(index, 1);
setRows(newRows);
}}
>
remove
</button>
</td>
</tr>
))}
</tbody>
</table>
);
};
解决方案
您的 onClick 处理程序应如下所示:
onClick={() => setRows(rows.filter(elem => elem.id != row.id ))}
如果您有一组对象,这是最好的方法。在现实世界的应用程序中,应该首先调用 API 来更改数据库中的数据,如果成功,然后才使用过滤器方法更新行状态。