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

React数组元素删除后子组件内容不匹配的原因排查

React列表删除后子组件内容与标题不匹配的原因分析

问题描述

在React组件中维护things数组,遍历数组时在父组件的div中展示元素名称,并将每个元素传入子组件展示详情。

问题现象:删除数组中除最后一个元素外的任意元素时,父组件的对应标题会正确消失,但子组件内容未同步更新,反而呈现出“最后一个元素被删除”的视觉效果——内容整体上移,导致标题与子组件展示的内容完全不匹配。

补充说明:子组件需要维护自身状态,实际场景中用于实现更新传入对象的表单,示例中简化移除了更新逻辑。

主组件代码

import { useState, useEffect } from "react";
import InnerComponent from "./InnerComponent";
import Thing from "./Thing";

import "./styles.css";

export default function App() {
  const [things, setThings] = useState<Thing[]>([]);

  useEffect(() => resetThings(), []);

  const resetThings = () => {
    setThings([
      { name: "dog", num: 5 },
      { name: "cat", num: 7 },
      { name: "apple", num: 11 },
      { name: "book", num: 1}
    ]);
  };

  const onDeleteThing = (indexToDelete: number) => {
    const newThings = [...things];
    newThings.splice(indexToDelete, 1);
    setThings(newThings);
  };

  return (
    <div className="App">
      {things.map((thing, index) => (
        <div key={`${index}`} className="thing-container">
          <h2>{thing.name}</h2>
          <InnerComponent
            thing={thing}
            index={index}
            onDelete={onDeleteThing}
          />
        </div>
      ))}
      <div>
        <button onClick={resetThings}>Reset Things</button>
      </div>
    </div>
  );
}

子组件代码

import { useEffect, useState } from "react";
import Thing from "./Thing";

interface InnerComponentParams {
  thing: Thing;
  index: number;
  onDelete: (indexToDelete: number) => void;
}

export const InnerComponent: React.FC<InnerComponentParams> = ({
  thing,
  index,
  onDelete
}) => {
  const [name, setName] = useState(thing.name);
  const [num, setNum] = useState(thing.num);

  return (
    <div>
      <div>Name: {name}</div>
      <div>Num: {num}</div>
      <div>
        <button onClick={(e) => onDelete(index)}>Delete Me</button>
      </div>
    </div>
  );
};

export default InnerComponent;

问题原因

1. 列表key使用数组索引导致组件错误复用

React依赖key属性识别列表元素的唯一性,以此决定是复用现有组件实例还是创建新实例。你当前使用数组的index作为key,当删除数组中间元素时,后续元素的索引会发生偏移:

  • 例如删除索引1的"cat"后,原索引2的"apple"会变为新的索引1,原索引3的"book"变为新的索引2。
  • React会认为key为1、2的组件已经存在,直接复用原有组件实例,仅更新它们的props,不会重新初始化组件状态。

2. 子组件状态未随props变化同步更新

子组件的name和num状态仅在组件首次挂载时,通过useState用初始props值初始化。之后即使父组件传入的thing props发生变化,子组件也不会自动更新自身状态。结合上述组件复用问题,就出现了标题与内容不匹配的现象:

  • 比如删除索引0的"dog"后,新数组的第一个元素是"cat",对应key为0。React会复用原来key=0的子组件实例(该实例的状态还是"dog"的信息),父组件标题显示"cat",但子组件仍展示"dog"的内容,最终导致错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:01:32