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

React中使用addEventListener和useState时如何修复闭包问题

问题根因

这是React Hooks场景下的典型闭包陷阱:

  • 你的事件绑定逻辑写在依赖数组为空的useEffect中,仅会在组件首次挂载时执行1次
  • 首次执行时绑定的handler函数,捕获的是首次渲染上下文中的num值(也就是初始值0)
  • 后续num更新触发组件重渲染时,会生成新的handler函数引用,但空依赖的useEffect不会重新执行,window上绑定的始终是第一次渲染时生成的旧handler,持有的永远是初始的0值,所以控制台始终输出0。

问题运行效果截图

修复方案

这里提供两种常用的修复方式,按需选择即可:

方案1:补全useEffect依赖,增加清理逻辑

将num加入useEffect的依赖数组,当num变化时自动解绑旧的事件监听、绑定持有最新num值的新监听,注意必须写清理逻辑避免内存泄漏。

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

function App() {
  const [num, setNum] = useState(0);

  const handler = () => {
    console.log(num);
  };

  useEffect(() => {
    window.addEventListener("click", handler);
    // 依赖更新/组件卸载时移除旧监听
    return () => window.removeEventListener("click", handler);
  }, [num]);

  return (
    <div className="App">
      <header className="App-header">
        <div
          onClick={() => {
            setNum(num + 1);
          }}
        >
          Add
        </div>
        <h1>{num}</h1>
      </header>
    </div>
  );
}

export default App;

方案2:使用useRef存储最新值,避免重复绑定事件

如果不想每次num更新都重绑事件,可以用useRef存储最新的num值,ref对象的current属性始终指向最新值,不会受闭包影响。

import "./App.css";
import { useState, useEffect, useRef } from "react";

function App() {
  const [num, setNum] = useState(0);
  // 用ref同步存储最新的num值
  const latestNum = useRef(num);
  useEffect(() => {
    latestNum.current = num;
  }, [num]);

  const handler = () => {
    // 从ref读取最新值
    console.log(latestNum.current);
  };

  useEffect(() => {
    window.addEventListener("click", handler);
    return () => window.removeEventListener("click", handler);
  }, []); // 仅在组件挂载时绑定一次即可

  return (
    <div className="App">
      <header className="App-header">
        <div
          onClick={() => {
            setNum(num + 1);
          }}
        >
          Add
        </div>
        <h1>{num}</h1>
      </header>
    </div>
  );
}

export default App;

注意:两种方案都需要在useEffect中返回清理函数移除事件监听,否则组件卸载后监听仍然存在,会造成内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:31:10