https://codesandbox.io/s/react-hooks-usefetch-cniul
有关我的代码的简化版本,请参见上面的网址。
我希望能够在一定时间间隔内(基本上是轮询端点以获取数据)使用钩子从API提取数据。
我想要的是能够仅调用refetch
之类的代码(如我在代码中作为注释所示),它实际上将再次调用fetchData
并使用做出相应的反应。
解决此问题的最佳方法是什么?我能想到的唯一方法是在钩子中添加一个checker
变量,该变量将是某种uuid(可能是Math.random()
),将setChecker
返回为refetch
并将checker
作为第二个useEffect参数添加到数组以控制重新渲染。因此,每当您调用refetch
时,它都会调用setChecker
来更新随机数(checker
),然后函数再次运行。
显然这听起来很“ hacky”,一定有更好的方法-有想法吗?
答案 0 :(得分:0)
如果您想进行持续的民意测验,我想您可以像这样将setInterval()
移入钩子:
function useFetch() {
const [data, setDataState] = useState(null);
const [loading, setLoadingState] = useState(true);
useEffect(() => {
function fetchData() {
setLoadingState(true);
fetch(url)
.then(j => j.json())
.then(data => {
setDataState(data);
setLoadingState(false);
});
}
const interval = setInterval(() => {
fetchData();
}, 5000);
fetchData();
return () => clearInterval(interval);
}, []);
return [
{
data,
loading
}
];
}
请记住包括return () => clearInterval(interval);
,以便正确清理钩子。
答案 1 :(得分:0)
import React, { useEffect, useState, useCallback } from "react";
import ReactDOM from "react-dom";
const url = "https://api.etilbudsavis.dk/v2/dealerfront?country_id=DK";
function useFetch() {
const [data, setDataState] = useState(null);
const [loading, setLoadingState] = useState(true);
const refetch = useCallback(() => {
function fetchData() {
console.log("fetch");
setLoadingState(true);
fetch(url)
.then(j => j.json())
.then(data => {
setDataState(data);
setLoadingState(false);
});
}
fetchData();
}, []);
return [
{
data,
loading
},
refetch
// fetchData <- somehow return ability to call fetchData function...
];
}
function App() {
const [
{ data, loading },
refetch
// refetch
] = useFetch();
useEffect(() => {
const id = setInterval(() => {
// Use the refetch here...
refetch();
}, 5000);
return () => {
clearInterval(id);
};
}, [refetch]);
if (loading) return <h1>Loading</h1>;
return (
<>
<button onClick={refetch}>Refetch</button>
<code style={{ display: "block" }}>
<pre>{JSON.stringify(data[0], null, 2)}</pre>
</code>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
答案 2 :(得分:0)
以下内容可能会起作用,需要对useFetch进行一些调整,但您仍然可以在其他地方正常调用它。
//maybe you can pass url as well so you can use
// it with other components and urls
function useFetch(refresh) {
//code removed
useEffect(() => {
//code removed
}, [refresh]);
//code removed
}
const [refresh, setRefresh] = useState({});
const [{ data, loading }] = useFetch(refresh);
useEffect(() => {
const interval = setInterval(
() => setRefresh({}), //forces re render
5000
);
return () => clearInterval(interval); //clean up
});
答案 3 :(得分:0)
简单回答问题:
export default function App() {
const [entities, setEntities] = useState();
const [loading, setLoadingState] = useState(true);
const getEntities = () => {
setLoadingState(true);
//Changet the URL with your own
fetch("http://google.com", {
method: "GET",
})
.then((data) => data.json())
.then((resp) => {
setEntities(resp);
setLoadingState(false);
});
};
useEffect(() => {
const interval = setInterval(() => {
getEntities();
}, 5000);
return () => clearInterval(interval);
}, []);
}