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

如何实现定时重渲染组件的队列?解决游戏头部轮播展示问题

问题分析与修复方案

现存问题点

  1. 变量名混乱:代码中混用name和nameFirstBlood状态,导致逻辑执行错乱,比如调用setNameFirstBlood但状态定义是name。
  2. 定时器叠加冲突:每次用户加入触发useEffect时都会创建新定时器,旧定时器未彻底清理,多个定时器同时执行导致名字切换速度异常。
  3. 首个用户展示延迟:后续用户加入时,旧定时器干扰了首个用户的展示流程,本该立即展示的内容被延迟。
  4. 超时恢复逻辑错误:每个用户单独设置恢复定时器,未考虑多用户轮播完成后再统一触发2分钟超时恢复。

修复后的实现代码

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

const [header, setHeader] = useState(headerLogo);
// 统一状态命名,包含用户数组和当前展示索引
const [leaderboard, setLeaderboard] = useState({
  users: [],
  currentIndex: 0
});
// 用ref存储定时器ID,跨useEffect清理
const carouselTimerRef = useRef(null);
const resetTimerRef = useRef(null);

// WebSocket消息监听:新增答对用户
useEffect(() => {
  if (!webSocket.current) return;
  
  const handleMessage = (event) => {
    if (event.data.startsWith('{')) {
      const rawData = event.data.replaceAll(`'`, `"`);
      const data = JSON.parse(rawData);
      
      setLeaderboard(prev => {
        // 避免重复添加同一用户(可根据业务调整判断条件)
        const isExist = prev.users.some(user => user.name === data.name);
        if (isExist) return prev;
        
        return {
          ...prev,
          users: [...prev.users, { name: data.name, score: data.score }],
          currentIndex: 0 // 新用户加入时重置展示顺序
        };
      });
    }
  };

  webSocket.current.onmessage = handleMessage;
  return () => {
    webSocket.current.onmessage = null;
  };
}, []); // 仅绑定一次监听,避免重复触发

// 头部轮播与超时恢复逻辑
useEffect(() => {
  // 清理旧定时器
  if (carouselTimerRef.current) clearTimeout(carouselTimerRef.current);
  if (resetTimerRef.current) clearTimeout(resetTimerRef.current);

  const { users, currentIndex } = leaderboard;
  const USER_DISPLAY_DURATION = 10000; // 单个用户展示10秒
  const TOTAL_RESET_DURATION = 120000; // 无新用户时2分钟恢复原标题

  if (users.length === 0) {
    setHeader(headerLogo);
    return;
  }

  // 立即展示当前索引的用户
  const currentUser = users[currentIndex];
  setHeader(
    <Header
      name={currentUser.name}
      score={currentUser.score}
    />
  );

  // 多用户轮播:非最后一个用户,10秒后切换下一个
  if (currentIndex < users.length - 1) {
    carouselTimerRef.current = setTimeout(() => {
      setLeaderboard(prev => ({
        ...prev,
        currentIndex: prev.currentIndex + 1
      }));
    }, USER_DISPLAY_DURATION);
  } else {
    // 最后一个用户展示完后,启动恢复定时器
    resetTimerRef.current = setTimeout(() => {
      setHeader(headerLogo);
      setLeaderboard({ users: [], currentIndex: 0 }); // 清空状态
    }, TOTAL_RESET_DURATION);
  }

  // 组件卸载或状态变化时清理定时器
  return () => {
    clearTimeout(carouselTimerRef.current);
    clearTimeout(resetTimerRef.current);
  };
}, [leaderboard, headerLogo]);

// localStorage同步逻辑(按需求保留)
useEffect(() => {
  localStorage.setItem('leaderboard', JSON.stringify(leaderboard));
}, [leaderboard]);

useEffect(() => {
  const saved = localStorage.getItem('leaderboard');
  if (saved) {
    setLeaderboard(JSON.parse(saved));
  }
}, []);

关键改动说明

  • 统一状态管理:用leaderboard状态整合用户数组和展示索引,避免变量名混淆。
  • 定时器Ref存储:确保每次状态变化时彻底清理旧定时器,解决叠加冲突问题。
  • 即时展示首个用户:数组有用户时立即展示当前内容,修复首个用户延迟问题。
  • 轮播+超时逻辑分离:多用户时按10秒间隔轮播,最后一个用户展示完后启动2分钟恢复定时器;新用户加入自动重置轮播流程。
  • WebSocket监听优化:仅绑定一次消息监听,避免重复触发导致的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:05:16