1

我有一个名为 fetchData 的函数。它的目的是根据 api 端点参数检索数据并根据间隔参数更新该数据。

import { useState, useEffect } from 'react';

export const fetchData = (endpoint, interval) => {
  const [jsonData, setJsonData] = useState(null);

  useEffect(() => {
    const innerFetchData = async () => {
      fetch(endpoint, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      })
        .then((res) => res.json())
        .then((data) => data)
        .then((moreData) => setJsonData(moreData))
        .catch((e) => console.error(e));
    };

    innerFetchData();

    const timer = setInterval(() => {
      innerFetchData();
    }, interval);
    return () => clearInterval(timer);
  }, []);

  return jsonData;
};

我正在导入它并在我的一个反应组件中使用它

const data = fetchData('/api/CustomerWorkspace', 5000);

出了问题的是我认为它没有正确读取间隔参数,当我运行它时,它可能每秒无限调用 api 50 次。如果我在 fetchData 内部的计时器上硬编码间隔时间,它可以正常工作。你能帮我弄清楚如何传递一个区间变量,以便我可以在不同的组件中重用 fetchData 吗?谢谢你。

4

3 回答 3

0

如果您innerFetchData();只在 setInterval 内调用,那么它会正常工作。您innerFetchData()在 useEffect 中调用了两次

于 2021-04-09T04:55:44.543 回答
0

尝试使用useInterval,一个自定义的钩子,可以处理这个浏览器 API 和 React 的一些奇怪问题。

简短:https ://www.30secondsofcode.org/react/s/use-interval

完整解释:https ://overreacted.io/making-setinterval-declarative-with-react-hooks/

应用演示:

// file: useInterval.js
export const useInterval = (callback, delay) => {
  const savedCallback = React.useRef();

  React.useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  React.useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
};

// your file
// import { useEffect, useState, useCallback } from "react"
// import { useInterval } from "./useInterval"
export const fetchData = (endpoint, interval) => {
  const [jsonData, setJsonData] = useState(null);
  
  const innerFetchData = useCallback(
    // if you gonna use `.then` you don't need the async in here tho
    async () => {
      fetch(endpoint, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      })
        .then((res) => res.json())
        .then((data) => data)
        .then((moreData) => setJsonData(moreData))
        .catch((e) => console.error(e));
    },
    [endpoint]
  );

  // runs once
  useEffect(() => {
    innerFetchData();
  }, []);
  
  // runs every `interval`
  useInterval(() => {
    innerFetchData();
  }, interval);

  return jsonData;
};

如果你愿意,你也可以把这个 fetchData 函数放在一个钩子里,调用它useFetchData,用法是一样的。不要改变我认为的任何东西,但我认为它更花哨的 xP

于 2021-04-09T05:03:17.127 回答
0

每次调用innerFetchData()时,它都会通过设置状态setJsonData 。这会触发重新渲染,导致 useEffect 删除您已经设置的间隔并立即创建一个新的。因此,您的时间间隔可能设置正确,但在每次请求时都会被清除。

您应该做的是将计时器存储在useRef. 这将有助于它在组件的整个生命周期中持续存在。

于 2021-04-09T05:28:44.510 回答