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

React子组件点击删除按钮后state未更新问题求助

React子组件状态未更新问题解惑

问题场景

对父组件中的videoData数组实现删除操作,子组件childComp映射渲染数组项,每个项对应删除按钮。点击删除按钮时,希望将当前项的id存入子组件的childData状态,但控制台打印childData始终为null,怀疑是父组件删除数据导致子组件回到初始状态。

代码示例

父组件代码

function ParentComp() {
  const [videoData, setvideoData] = useState([{ id: 2 }, { id: 3 }]);
  function testFunc(id) {
    let hasMatch = false
    if (!hasMatch) {
      let arr = videoData.filter(item => {
        return item.id !== id
      })
      setvideoData(arr)
    }
  }
  return (
    <childComp testFunc={testFunc} videoData={videoData}/>
  )
}

子组件代码

function childComp({testFunc, videoData}) {
  const [childData, setchildData] = useState(null)
  function ChildFunc(itemId) {
    testFunc(itemId)
    setchildData(itemId)
  } 
  console.log(childData)  // 始终打印null
  return (
    <>
    {videoData.map((item) => {
      return (
        <button onClick={() => ChildFunc(item.id)}>Delete</button>
      );
    })}
  </>
  )
}

原因分析

你的猜想不完全正确,核心问题是React状态更新的异步特性以及组件渲染时机:

  1. 点击按钮后,先调用父组件的testFunc,父组件更新videoData状态,触发子组件重新渲染。此时子组件的setchildData还未完成异步更新,所以这次重新渲染时childData仍为null,控制台打印出这个值。
  2. 随后setchildData的异步更新完成,子组件会再次重新渲染,此时childData已经是目标id,但你放在组件函数体中的console.log会在每次渲染时执行,你可能只注意到了第一次重新渲染的null输出,忽略了后续的正确值。

另外,父组件中hasMatch变量固定为false,属于冗余代码,不影响功能但可以优化。

解决方案

  1. 正确监听状态变化:使用useEffect监听childData的变化,这样能准确捕获状态更新后的结果:
import { useEffect } from 'react';

function childComp({testFunc, videoData}) {
  const [childData, setchildData] = useState(null)
  
  useEffect(() => {
    console.log('childData 更新后的值:', childData);
  }, [childData]); // 仅在childData变化时执行

  function ChildFunc(itemId) {
    testFunc(itemId)
    setchildData(itemId)
  } 

  return (
    <>
    {videoData.map((item) => {
      return (
        <button onClick={() => ChildFunc(item.id)}>Delete</button>
      );
    })}
  </>
  )
}
  1. 优化父组件状态更新:使用函数式更新避免闭包问题,同时移除冗余的hasMatch变量:
function ParentComp() {
  const [videoData, setvideoData] = useState([{ id: 2 }, { id: 3 }]);
  function testFunc(id) {
    // 用函数式更新,确保拿到最新的videoData状态
    setvideoData(prevData => prevData.filter(item => item.id !== id));
  }
  return (
    <childComp testFunc={testFunc} videoData={videoData}/>
  )
}

补充说明

子组件的childData状态是独立的,父组件videoData的更新只会触发子组件重新渲染,不会重置子组件的状态。只要状态更新逻辑正确,childData最终会被设置为目标id,只是需要用正确的方式监听状态变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:13:59