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

点击按钮后React状态异常:数组元素被替换而非新增

问题分析与解决方案

问题根源

你碰到的是React的闭包陷阱:组件每次渲染时,事件处理函数会捕获当前渲染周期的state快照。后续点击按钮触发函数时,引用的始终是最初的state值,而非更新后的最新状态。

比如_testCount里的setCount(count + 1),每次点击都是基于初始的count=0计算,所以永远只能得到1;_handleDownload里的downloadedBatches始终是空数组,导致每次新增后数组只有当前点击的ID,旧的被覆盖。

修复代码

改用React状态更新的函数式写法,直接基于最新的state计算新值:

const Example = () => {
  const [downloadedBatches, setDownloadedBatches] = useState<any>([]);
  const [count, setCount] = useState<number>(0);
      
  const _handleDownload = ({ currentTarget: { dataset: { id } } }: any) => {
    if (!downloadedBatches.includes(id)) {
      // 函数式更新,prevState是当前最新的数组状态
      setDownloadedBatches(prevState => [...prevState, id])
    }
    console.log(`Downloaded Batch #${id}`)
  }
    
  const _testCount = () => {
    // 基于最新count值计算更新
    setCount(prevCount => prevCount + 1);
  };
    
  return (
    <>
      <Button icon={'download'} onClick={_handleDownload} data-id={1}/>
      <Button icon={'download'} onClick={_handleDownload} data-id={2}/>
      <Button icon={'download'} onClick={_handleDownload} data-id={3}/>
      <Button icon={'download'} onClick={_testCount} data-id={3}/>
    </>
  )  
}

补充说明

  • 函数式更新会自动传入当前最新的state作为参数,确保每次更新都基于最新状态计算,彻底避免闭包导致的旧值引用问题。
  • 额外补充:React要求组件返回的JSX必须有单一根元素,所以修复代码里用<>片段包裹了所有Button,避免渲染报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:01:17