I have a grid with different react components, all independant - in that they fetch their own data and display it.
I wanted to somehow make them automatically refetch and update every 15 minutes. My first idea was a HOC, but with the newer hooks and functional components I tried something using hooks.
So I already was able to create a custom hook - to handle the fetching of data:
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
};
};
Then two components using this:
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'));
This works fine - using the custom hook. So I was thinking something in the lines of:
Set up an interval timer which runs ever 15 minutes and changes the 'reload' state flag - to trigger a refetch and update. Also make sure the interval timer is unset on component unload.
To access the state and the setReload method - I placed the timer inside of the useFetching component - but that didn't work as it fired up multiple timers. I think I had 14 timers for only two components.
I'm really unsure of how to proceed - I would like one timer only handling the refresh of all components - at the same time I want the components to be independant and not have to share anything with an external timer. It would be fine with one timer per component - as long as it properly destroyed when the component is unloaded - and it would be nice if this mechanism is built into the useFetching hook.
Is there a much better way to build this - that I'm not thinking of?
Suggestions much appreciated!