我有一个名为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吗?非常感谢。
尝试使用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
,用法相同。我认为不要改变任何东西,但imo更花哨的xP
如果只在setInterval内调用innerFetchData();
,那么它会正常工作。您在useEffect 中调用innerFetchData()
两次
每次调用innerFetchData()
时,它都会通过setJsonData
设置状态。这会触发重新应答,导致useEffect删除您已经设置的间隔,并立即创建一个新的间隔。因此,您的间隔可能设置正确,但每次请求都会清除。
您应该做的是将计时器存储在useRef
中。这将有助于它在组件的整个生命周期中持续存在。