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

React函数组件按键递增异常:SetState(state+1)触发翻倍加一问题

问题原因

你的代码每次组件渲染时都会重复给window绑定keydown事件监听器,导致每按一次键,所有已绑定的监听器都会触发。每个监听器里的displayText是闭包捕获的当时的状态值,多次触发后就会出现数字翻倍加1的异常结果。

修复方案

使用useEffect管理事件监听器,确保只绑定一次,同时用函数式更新获取最新状态值:

const Display = (props) => {
  return ( 
    <div id="display">{props.text}</div>
  )
}

const App = () => {
  const [displayText, setDisplayText] = React.useState(0);

  React.useEffect(() => {
    const handleKeyDown = (e) => {
      // 函数式更新,基于最新状态计算新值
      setDisplayText(prev => prev + 1);
    };

    window.addEventListener('keydown', handleKeyDown);

    // 组件卸载时移除监听器,避免内存泄漏
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, []); // 空依赖数组:仅在组件挂载时执行一次

  return (
    <div className="container">
      <Display text={displayText} />
    </div>
  )
}
关键说明
  • useEffect 管理监听器:空依赖数组的useEffect只会在组件首次挂载时执行一次绑定,返回的清理函数会在组件卸载时移除监听器,彻底解决重复绑定的问题。
  • 函数式状态更新:setDisplayText(prev => prev + 1) 直接使用React维护的最新状态值计算新值,避免闭包捕获旧值导致的错误。
  • 注意React元素中需用className替代HTML的class属性,避免语法冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 08:54:17