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

React组件每隔5秒刷新至满足停止条件的状态读取问题

问题原因分析

你的代码核心问题是闭包捕获旧值:useEffect的依赖数组为空,意味着它只会在组件首次渲染时执行一次,里面的status变量被闭包捕获,永远是初始值''。后续setStatus更新状态后,定时器里的status不会同步更新,导致停止逻辑永远无法触发。

解决方案

方案1:使用useRef保存最新状态(推荐)

useRef的current属性是可变的,不会被闭包捕获,能始终拿到最新的status值:

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

const YourComponent = () => {
  const [status, setStatus] = useState(''); // 0:failed, 1:waiting, 2:success
  const statusRef = useRef(status);

  // 同步最新status到ref
  useEffect(() => {
    statusRef.current = status;
  }, [status]);

  useEffect(() => {
    const interval = setInterval(() => {
      // 读取ref中的最新状态
      if (statusRef.current !== '2' && statusRef.current !== '0') {
        handleClickRefresh();
      } else {
        // 满足停止条件时清除定时器
        clearInterval(interval);
      }
    }, 5000);

    // 组件卸载或重新渲染时清除定时器
    return () => clearInterval(interval);
  }, []);

  const handleClickRefresh = async () => {
    try {
      const res = await axios.get('...', {
        headers: {
          // 你的请求头配置
        }
      });
      if (res.status === 202) {
        setStatus('1'); // waiting
      } else if (res.status === 200) {
        setStatus('2'); // success
      }
    } catch (error) {
      setStatus('0'); // fail
    }
  };

  return (
    <div>当前状态:{status}</div>
  );
};

export default YourComponent;

说明

  • 用statusRef同步最新的status值,确保定时器能拿到实时状态
  • 当状态变为2(成功)或0(失败)时,立即清除定时器停止刷新
  • 仅在组件首次渲染时创建一次定时器,避免频繁销毁重建的性能损耗

方案2:给useEffect添加status依赖

通过监听status变化,动态创建/销毁定时器:

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

const YourComponent = () => {
  const [status, setStatus] = useState(''); // 0:failed, 1:waiting, 2:success

  useEffect(() => {
    // 已达到停止条件,无需创建定时器
    if (status === '2' || status === '0') return;

    const interval = setInterval(() => {
      handleClickRefresh();
    }, 5000);

    return () => clearInterval(interval);
  }, [status]); // 依赖status,状态变化时重新执行

  const handleClickRefresh = async () => {
    try {
      const res = await axios.get('...', {
        headers: {
          // 你的请求头配置
        }
      });
      if (res.status === 202) {
        setStatus('1'); // waiting
      } else if (res.status === 200) {
        setStatus('2'); // success
      }
    } catch (error) {
      setStatus('0'); // fail
    }
  };

  return (
    <div>当前状态:{status}</div>
  );
};

export default YourComponent;

说明

  • 每次status变化时,旧定时器会被清除,再根据新状态决定是否创建新定时器
  • 逻辑更直观,但状态变化频繁时会多次创建/销毁定时器,性能略逊于方案1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:20:33