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

React开发Chrome同款恐龙跑酷游戏时setInterval触发快于设置值问题

React开发恐龙跑酷游戏定时器触发频率异常排查

我正在用React开发一款类似谷歌Chrome内置的恐龙跑酷游戏。

我的思路是在障碍物预计与恐龙发生碰撞的时刻(约3秒)运行对应检测函数,代码如下:

function check4Death() {
  if (playerClass !== '') {
    console.log('safe')
  }
  else {
    console.log('nope')
    clearInterval()
  }
}
setInterval(check4Death, 3000)

该函数用于检测玩家当前是否处于空中:我的跳跃实现方式是给playerClass对象添加jump类,之后再移除该类,跳跃功能的代码如下:

function Jump() {
  setPlayerClass('jump')
  setTimeout(() => {
    setPlayerClass('')
  }, 500);
}

但实际运行时,该函数没有按照预期每3秒输出一次safe或nope,反而触发频率远高于设置值,运行效果见下图:
运行效果截图


问题根因

  • 定时器重复创建:你将setInterval直接写在了React函数组件的顶层作用域中,只要组件触发重渲染(比如playerClass状态更新),就会重新执行组件逻辑,新建一个定时器。运行时间越长,并行的定时器数量越多,触发频率自然远高于设定的3秒间隔。
  • 清除逻辑无效:clearInterval调用必须传入对应定时器的ID作为参数,你当前的调用没有传参,就算触发else分支也不会清除任何运行中的定时器。
  • 缺少销毁逻辑:组件卸载时没有主动清除定时器,会造成内存泄漏。

修复方案

使用useEffect+useRef管理定时器,确保全局仅存在一个碰撞检测定时器,参考代码如下:

import { useEffect, useRef, useState } from 'react'

function DinoGame() {
  const [playerClass, setPlayerClass] = useState('')
  // 用useRef存储定时器ID,跨渲染周期保持取值稳定
  const collisonTimerRef = useRef(null)

  // 组件首次挂载时初始化定时器
  useEffect(() => {
    collisonTimerRef.current = setInterval(check4Death, 3000)
    // 组件卸载时清除定时器,避免内存泄漏
    return () => clearInterval(collisonTimerRef.current)
  }, [])

  function check4Death() {
    if (playerClass !== '') {
      console.log('safe')
    } else {
      console.log('nope')
      // 传入定时器ID完成清除
      clearInterval(collisonTimerRef.current)
    }
  }

  function Jump() {
    // 增加跳跃状态判断,避免重复触发跳跃
    if (playerClass === 'jump') return
    setPlayerClass('jump')
    setTimeout(() => {
      setPlayerClass('')
    }, 500)
  }

  // 剩余组件渲染逻辑省略
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:36:03