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

React项目中重连按钮点击后CountDown无法持续渲染问题求助

问题分析与解决方案

核心问题

  1. 闭包捕获旧状态:reconnectFunction里的setInterval创建时捕获了当时的countDown初始值(60),后续每次执行setCountDown(countDown - 1)都是把状态设为59,不会继续递减。
  2. 重复创建定时器:每次点击“重连”都会新建一个定时器,旧定时器未清理,导致控制台重复输出,状态更新混乱。

解决步骤

  • 使用函数式更新获取最新状态值,规避闭包陷阱。
  • 用useRef存储定时器ID,确保能清理旧定时器,防止内存泄漏和重复执行。
  • 点击重连时重置倒计时,连接成功后关闭模态框并清除定时器。

修改后的代码

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

const ChatComponent = () => {
  const [countDown, setCountDown] = useState(60);
  const [reconnectModal, setReconnectModal] = useState(false);
  const timerRef = useRef(null); // 存储定时器ID

  // 组件卸载时清理定时器
  useEffect(() => {
    return () => {
      if (timerRef.current) {
        clearInterval(timerRef.current);
      }
    };
  }, []);

  const connect = () => {
    // 替换为实际的Websocket连接逻辑
    const ws = new WebSocket('ws://your-chat-server-url');
    ws.onopen = () => {
      // 连接成功后关闭模态框并清除定时器
      setReconnectModal(false);
      if (timerRef.current) {
        clearInterval(timerRef.current);
        timerRef.current = null;
      }
    };
    ws.onerror = () => {
      // 连接失败时显示模态框
      setReconnectModal(true);
    };
  };

  const reconnectFunction = () => {
    // 重置倒计时为初始值
    setCountDown(60);
    // 清除之前的定时器,避免重复执行
    if (timerRef.current) {
      clearInterval(timerRef.current);
    }
    // 启动新的倒计时定时器
    timerRef.current = setInterval(() => {
      setCountDown(prevCount => {
        // 倒计时到0时停止定时器
        if (prevCount <= 1) {
          clearInterval(timerRef.current);
          timerRef.current = null;
          return 0;
        }
        return prevCount - 1;
      });
    }, 1000);
    // 触发重连
    connect();
  };

  return (
    <Modal
      visible={reconnectModal}
      okText={`Reconnect (${countDown})`}
      cancelText="Close"
      onOk={reconnectFunction}
      onCancel={() => {
        setReconnectModal(false);
        // 关闭模态框时清理定时器
        if (timerRef.current) {
          clearInterval(timerRef.current);
          timerRef.current = null;
        }
      }}
    >
      Connection failed. Please try again
    </Modal>
  );
};

export default ChatComponent;

关键细节说明

  • 函数式更新:setCountDown(prev => prev - 1)确保每次都基于最新的状态值更新,避免闭包捕获旧值的问题。
  • 定时器管理:通过useRef保存定时器ID,在组件卸载、连接成功、关闭模态框时都清理定时器,防止内存泄漏和重复执行。
  • 状态重置:每次点击重连时重置倒计时为60,保证用户每次操作都从初始值开始倒计时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:20:25