我有一个网格,其中包含不同的反应组件,所有组件都是独立的 - 因为它们获取自己的数据并显示它。
我想以某种方式使它们每 15 分钟自动重新获取和更新一次。我的第一个想法是 HOC,但对于较新的钩子和功能组件,我尝试使用钩子进行了一些操作。
所以我已经能够创建一个自定义钩子 - 处理数据的获取:
const useFetching = (url) => {
const [loading, setLoading] = useState(true);
const [data, setData] = useState({});
const [error, setError] = useState(null);
const [reload, setReload] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Something went wrong');
}
const json = await response.json();
if (json) {
setData(json);
}
} catch (error) {
setError(error);
}
setLoading(false);
}
fetchData();
}, [url, reload]);
return {
loading,
data,
error
};
};
然后两个组件使用它:
const App1 = () => {
const {loading, data, error} = useFetching(
"https://hn.algolia.com/api/v1/search?query=redux"
);
if (loading || error) {
return <p>{loading ? "Loading..." : error.message}</p>;
}
return (
<ul>
{data.hits.map(hit =>
<li key={hit.objectID}>
<a href={hit.url}>{hit.title}</a>
</li>
)}
</ul>
);
};
const App2 = () => {
const {loading, data, error} = useFetching(
"https://hn.algolia.com/api/v1/search?query=balls"
);
if (loading || error) {
return <p>{loading ? "Loading..." : error.message}</p>;
}
return (
<ul>
{data.hits.map(hit =>
<li key={hit.objectID}>
<a href={hit.url}>{hit.title}</a>
</li>
)}
</ul>
);
};
ReactDOM.render(<><App1 /><App2/></>, document.getElementById('root'));
这工作正常 - 使用自定义钩子。所以我在想一些事情:
设置一个间隔计时器,每 15 分钟运行一次并更改"重新加载"状态标志 - 以触发重新获取和更新。还要确保在组件卸载时未设置间隔计时器。
要访问状态和 setReload 方法 - 我将计时器放在 useFetching 组件内 - 但这不起作用,因为它触发了多个计时器。我想我只有两个组件有 14 个计时器。
我真的不确定如何进行 - 我想要一个计时器只处理所有组件的刷新 - 同时我希望组件是独立的,不必与外部计时器共享任何东西。每个组件一个计时器就可以了 - 只要它在卸载组件时正确销毁 - 如果这种机制内置到 useFetching 钩子中会很好。
有没有更好的方法来构建这个 - 我没有想到?
建议非常感谢!
你需要一个useInterval
钩子。这篇文章确切地解释了原因和方式:https://overreacted.io/making-setinterval-declarative-with-react-hooks/
由于useFetch
封装了单个组件的获取逻辑,因此每个组件管理自己的间隔是有意义的。您可以通过在挂载时声明一个将在 15 分钟后触发的间隔来实现这一点。
useEffect(() =>{
let interval = setInterval(() => setReload(true), (1000 * 60 * 15))
//destroy interval on unmount
return () => clearInterval(interval)
})
有关useEffect
的更多信息(包括上述效果清理(。