React中无法按索引删除动态div对应的数组指定元素如何解决?
问题原因
你当前的写法存在三个核心错误,这也是你删除一个元素就丢失后面所有元素的直接原因:
- 闭包陷阱:你每个列表项绑定的删除函数都捕获了列表项创建时的
Children状态,这个状态是固定的旧值,不是最新的列表数组。比如你新增第7个元素时,当时的Children长度为6,后续你再新增到10个元素,点击第7个元素的删除按钮时,函数拿到的还是长度为6的旧数组,你操作旧数组更新状态后,就会把之后新增的所有元素都覆盖丢失。 - 不应该直接把生成好的JSX元素存储在useState中,React的状态应该只存放原始业务数据,UI由数据渲染生成,直接存储JSX会导致内部绑定的事件、状态全部固化,无法跟随数组变化同步更新。
- 每个删除按钮绑定的是列表项创建时的静态索引,你删除前面的元素后,后续列表项的实际索引已经发生变化,但按钮绑定的还是旧索引,会导致后续删除操作位置错乱。
修正方案
把状态改为存储列表原始数据,渲染时再遍历数据生成对应的UI,删除时根据数据的唯一标识操作数据即可,修正后的代码如下:
const { useState } = React; function Check(){ // state只存列表原始业务数据,不存储渲染后的JSX const [listData, setListData] = useState([]) function RemArr(targetId){ // 用函数式更新保证拿到最新的状态,过滤掉要删除的项 setListData(prev => prev.filter(item => item.id !== targetId)) } function addList() { // 新增时给每个项加唯一标识,避免用索引做删除依据的不稳定问题 setListData(prev => [...prev, { id: Date.now(), fix: false }]) } return (<React.Fragment> <div>Check</div> {/* 遍历数据动态生成UI,每次渲染都会拿到最新的索引和绑定最新的事件 */} {listData.map((item, index) => ( <React.Fragment key={item.id}> <button onClick={()=>RemArr(item.id)}> List {index} </button> <p></p> <input/> <p></p> </React.Fragment> ))} <button onClick={addList}> Add List </button> </React.Fragment>) } ReactDOM.render(<Check />, document.body);
配套HTML代码保持不变:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
内容的提问来源于stack exchange,提问作者Monirul
相关产品推荐
相关产品推荐

