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

为何监听useRef变化的useEffect仅触发一次console.log?期望每秒执行

问题分析与解决方案

核心问题原因

React的useEffect只有在组件发生重渲染时才会重新计算依赖项并执行副作用。而useRef的current属性修改不会触发组件重渲染,所以你给第一个useEffect设置的[changeRef.current]依赖完全无效——组件没重渲染,React不会去检查这个依赖是否变化,自然只会在首次渲染时执行一次。

解决方案1:无需组件重渲染,仅实现每秒打印

直接在定时器内同步更新prevValueRef并打印,不需要借助useEffect监听:

const PreviousValueComponent = ({ value }) => {
  const prevValueRef = useRef();
  const changeRef = useRef(value);

  useEffect(() => {
    const interval = setInterval(() => {
      prevValueRef.current = changeRef.current;
      console.log(`prevValueRef is: ${prevValueRef.current}`);
      changeRef.current++;
    }, 1000);

    // 组件卸载时清理定时器,避免内存泄漏
    return () => clearInterval(interval);
  }, []);

  return (
    <div>
      <p>Current Value: {value}</p>
      <p>Previous Value: {prevValueRef.current}</p>
    </div>
  );
};

解决方案2:需要页面UI同步更新(可选)

如果要让页面上的Previous Value文本实时更新,必须用useState触发组件重渲染(因为ref变化不会更新UI):

const PreviousValueComponent = ({ value }) => {
  const [prevValue, setPrevValue] = useState(value);
  const changeRef = useRef(value);

  useEffect(() => {
    const interval = setInterval(() => {
      changeRef.current++;
      setPrevValue(changeRef.current);
      console.log(`prevValueRef is: ${changeRef.current}`);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return (
    <div>
      <p>Current Value: {value}</p>
      <p>Previous Value: {prevValue}</p>
    </div>
  );
};

对补充问题的答复

你的实现方式确实有误:useEffect的依赖更新机制依赖组件重渲染,而ref.current的修改不会触发重渲染,所以React不会重新检查该依赖项,也就不会执行副作用。如果要监听ref变化,要么在修改ref的地方直接执行逻辑,要么结合useState触发重渲染让React重新计算依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:06:25