I am trying to set an interval on mount/unmount only, but allow the callback to have one variable from state.
I have code like this:
const [cachedData, setCachedData] = useState(false);
async function refreshData() {
const data = await axios('http://www.example.com/');
setCachedData(data);
}
useEffect(() => {
let interval;
async function fetch() {
await refreshData();
interval = setInterval(refreshData,5000);
console.log('set interval to', interval)
}
fetch();
return () => {
console.log('clearing interval', interval);
clearInterval(interval);
}
}, []);
I am running into a catch-22. The second argument of useEffect says what variables to pay attention to. I've read making it an empty array makes this only mount/unmount rather than on any state updates. The issue I've found is that doing that, means refreshData has no access to cachedData, so I can't know I have valid data (to avoid the XHR request for an amount of time). If I pass cachedData into second argument of useEffect, it will have the variable but run more than it should. Not sure of a way around this.
I should note that if I pass cachedData to the second arg, and console.log by the clear and the setting of the interval, my console outputs something like this:
clearing interval undefined
set interval to 5
set interval to 7
So it seemingly runs the unmount and then the effect twice over without clearing again. This causes a double axios call.
You can use a ref to get at the current cachedData with something like the following:
const [cachedData, setCachedData] = useState(false);
const cachedDataRef = useRef(cachedData);
useEffect(() => {
// Update ref in effect so that render has no side effects.
cachedDataRef.current = cachedData;
}, [cachedData]);
useEffect(() => {
async function refreshData() {
if (cachedDataRef.current) {
// do something different
} else {
const data = await axios('http://www.example.com/');
setCachedData(data);
}
}
let interval;
async function fetch() {
await refreshData();
interval = setInterval(refreshData,5000);
console.log('set interval to', interval)
}
fetch();
return () => {
console.log('clearing interval', interval);
clearInterval(interval);
}
}, []);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With