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

React中useState配合setInterval实现组件移动时计数异常问题

React组件移动异常:状态递增与日志输出不符的原因

作为React新手,我想实现一个持续移动的组件,通过递增transform: translate的坐标值来实现,但状态递增结果和日志输出不符合预期。

我的代码如下:

function Point() {
  const [countX, setCountX] = useState(0);
  const [countY, setCountY] = useState(0);

  setInterval(() => {
    setCountX((count) => count + 1);
    setCountY((count) => count + 1);

    console.log(countX + ":" + countY);
  }, 500);

  const styles = {
    transform: `translate(${countX}px,${countY}px)`,
  };

  return <PointStyle style={styles} />;
}

控制台输出的日志如下:

0:0
1:1
0:0
2:2
1:1
4:4
0:0
5:5
2:2
7:7
1:1
9:9
4:4
10:10
11:11
0:0
12:12
5:5
14:14
2:2
7:7

问题原因

  • 多个定时器同时运行:每次组件状态更新都会触发重渲染,你直接在组件函数里调用setInterval,导致每次渲染都新建一个定时器。这些定时器会同时修改状态,造成数值混乱。
  • 闭包捕获旧状态:定时器的回调函数是在组件某一次渲染时创建的,它捕获的是当时的countX和countY值(也就是旧状态)。所以你在回调里打印的永远是创建该定时器时的旧状态,不是最新的状态值。

修复方案

用useEffect来管理定时器,确保只在组件挂载时创建一次,且卸载时清理:

import { useState, useEffect } from 'react';

function Point() {
  const [countX, setCountX] = useState(0);
  const [countY, setCountY] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCountX(prev => prev + 1);
      setCountY(prev => prev + 1);
    }, 500);
    
    // 组件卸载时清除定时器
    return () => clearInterval(timer);
  }, []); // 空依赖数组,只执行一次

  const styles = {
    transform: `translate(${countX}px,${countY}px)`,
  };

  return <PointStyle style={styles} />;
}

如果需要打印最新的状态值,可以额外加一个useEffect来监听状态变化:

useEffect(() => {
  console.log(countX + ":" + countY);
}, [countX, countY]); // 当countX或countY变化时执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 08:05:23