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

React中addEventListener内使用useState修改状态不生效如何解决?

React右键点击修改state不生效问题解决方案

问题原因

  • 依赖与判断逻辑错误:testRef 是 React 生成的稳定 ref 对象,本身不会随渲染变化,原有代码判断!testRef永远为假,实际应该判断!testRef.current才是检测DOM是否挂载完成。
  • 闭包陷阱:原有事件绑定逻辑仅在组件首次挂载时执行一次,捕获的testState永远是初始值0,所以即使触发更新也只会把值设为1,之后再触发不会产生新的状态变化,自然不会触发监听testState的useEffect打印日志。
  • 缺少事件清理逻辑:绑定的右键事件没有在组件卸载时移除,会造成内存泄漏。
  • 未阻止右键默认行为:原生contextmenu事件默认会弹出浏览器右键菜单,可根据需求阻止默认行为。

修复方案

修改后的完整代码如下:

import { useState, useRef, useEffect } from "react";

function Main() {
  const [testState, setTestState] = useState(0);
  const testRef = useRef(null);

  useEffect(() => {
    // 正确判断DOM是否挂载完成
    if (!testRef.current) return;
    const el = testRef.current;

    const clickHandler = (event) => {
      // 阻止默认右键菜单弹出,不需要可以删除该行
      event.preventDefault();
      // 使用函数式更新规避闭包问题,不需要依赖当前作用域的testState
      setTestState(prev => prev + 1);
    }

    el.addEventListener('contextmenu', clickHandler);
    // 组件卸载/依赖变化时清理事件,避免内存泄漏
    return () => {
      el.removeEventListener('contextmenu', clickHandler);
    };
  // 该副作用无外部依赖,依赖数组为空即可
  }, []);

  useEffect(() => {
    console.log('testState: ', testState);
  }, [testState]);

  return (
    <div
      ref={testRef}
      style={{width: '100%', display: 'block', height: '32px', backgroundColor: 'red'}}
    />
  );
}

export default Main;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 20:06:03