使用setInterval和访存时如何清理useEffect?

时间:2020-08-04 17:53:06

标签: reactjs asynchronous jsx setinterval react-functional-component

我尝试了很多选择,但似乎没有任何办法可以解决问题。我不断收到警告“无法在已卸载的组件上执行React状态更新”。我是编程新手,所以对您而言,如此简单可能很容易。我试过在useEffect内设置一个变量,以了解是否已安装该组件,并且仅在变量的值为true时更新状态,然后在return函数中将其设置为false。我也尝试过使用abortController,但是这两种情况都不适合我。这是我的代码:

import React, { useState, useEffect } from "react";
import CircularGraphs from "./CircularGraphs";
import Loader from "../components/Loader";

function Statistic(props) {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState("");
  const getData = () => {
    fetch(`http://localhost:3009/statistic`)
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        setData(data);
        setLoading(false);
      });
  };
  useEffect(() => {
    if (data === "") {
      setLoading(true);
      getData();
    } else {
      const interval = setInterval(() => {
        getData();
      }, 5000);
      return () => {
        clearInterval(interval);
      };
    }
  }, [data]);
  return (
    <div
      className={
        props.activeItem === 2 ? "second-item show" : "second-item hidden"
      }
    >
      <div className="sidebar-right-expanded-title">
        <h6>Estadistica</h6>
        <h5 className="sidebar-right-expanded-sucursal">Matriz</h5>
      </div>
      {loading ? (
        <Loader />
      ) : (
        <React.Fragment>
          <div className="graph-container">
            <div className="day-graph-container">
              <CircularGraphs percentage={data.today ? data.today : 50} />
              <p>NV-día</p>
            </div>
          </div>
          <div className="day-month-graph-container">
            <div className="previousday-graph-container">
              <CircularGraphs
                percentage={data.previousDay ? data.previousDay : 50}
              />
              <p>NV-día anterior</p>
            </div>
            <div className="month-graph-container">
              <CircularGraphs percentage={data.month ? data.month : 50} />
              <p>NV-mes</p>
            </div>
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

export default Statistic;

1 个答案:

答案 0 :(得分:0)

因此,我将通过告诉我在这些情况下的操作来尝试提供帮助:

  1. const [data, setData] = useState("");不会将默认状态设置为空字符串,而是如果您已经知道您将收到类似内容的对象,请进行模拟

    const [data, setData] = useState({today: 50, previousDay: 50, month: 50});
    
  2. 对于lodaer,您可以在getData中设置加载程序,这样您就知道加载程序将在调用getData时启动,并在您收到响应或错误时停止,并且您可以直接设置间隔而不进行测试,因为您每5秒要数据

  3. 如果希望一次触发getData,则无需使用计时器即可使用setTimout

  4. 如果您希望每5秒调用一次getData,则应该进行清理,我猜应该返回clearInterval(interval); (我不确定)