You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React删除列表中间项时出现最后一项被移除的异常问题求助

问题根因

你遇到的输入框内容移位问题由三个错误实现共同导致:

  1. 不该将React组件实例直接存储在state中,state仅应存储纯业务数据,直接存组件实例会导致实例和状态强绑定,无法正常触发更新
  2. 列表渲染时未设置唯一key属性,React虚拟DOM diff默认会用数组索引作为key,删除中间元素后后续元素索引整体前移,React会判定删除的是最后一个元素,仅移除末尾DOM、复用前面的DOM节点
  3. ListElement的输入框为未受控组件,输入的内容仅存储在DOM节点本身,没有和React状态绑定,DOM复用时之前输入的内容会被保留,自然出现移位

修复方案

父组件代码

import { useState } from 'react';
import ListElement from './ListElement';
import { MdRemoveCircleOutline } from 'react-icons/md';

export default function ListPage() {
    // state仅存储列表纯数据,每个项配备唯一id
    const [itemList, setItemList] = useState([]);

    const removeItem = (id) => {
        const updatedList = itemList.filter(item => item.id !== id);
        setItemList(updatedList);
    };

    const addItem = () => {
        const newItem = {
            id: Date.now(), // 用时间戳生成唯一id
            inputValue: ''
        };
        setItemList([...itemList, newItem]);
    };

    // 同步子组件输入框的值到上层状态
    const syncInputValue = (id, newValue) => {
        setItemList(itemList.map(item => {
            return item.id === id ? {...item, inputValue: newValue} : item;
        }));
    };

    return (
        <div className="list-page">
            <div className="list-page-title">
                <h2>Create your own List</h2>
                <br></br>
                <h4>Create your own list</h4>
            </div>
            <input
                className="title-input"
                type="text"
                placeholder="Enter Title"
            />
            <div className="list-content">
                {itemList.map((item) => {
                    return (
                        // 用唯一id作为key,禁止用数组索引
                        <div key={item.id}>
                            <ListElement
                                handleRemove={() => removeItem(item.id)}
                                value={item.inputValue}
                                onInputChange={(val) => syncInputValue(item.id, val)}
                            />
                        </div>
                    );
                })}
            </div>

            <button className="add-button" onClick={addItem}>
                <span className="list-page-button-icon">+</span>Add Item
            </button>
        </div>
    );
}

ListElement组件代码

export default function ListElement(props) {
    return (
        <div className="list-item">
            <input
                className="item-input"
                type="text"
                value={props.value}
                onChange={(e) => props.onInputChange(e.target.value)}
                placeholder="请输入内容"
            ></input>
            <MdRemoveCircleOutline
                className="remove-button"
                onClick={props.handleRemove}
            />
        </div>
    );
}

内容的提问来源于stack exchange,提问作者bmarcu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 06:42:00