Reputation: 5379
The code below is just a mock up of a screen that appears when there's an error in loading data (specifically temporary network loss). What I'm trying to do is on mount run the 'refresh' function and keep running it every 10 seconds until the variable 'online' changes from 'false' to 'true'. Here I change it with a button, in the real screen it'll be an async call to load data (if data loaded, it'll become true). So the idea is to keep trying to load data.
What happens in the code below is it console logs 'still offline' every 10 seconds but then when I press the button, it correctly logs 'back on line' but then it goes back to logging 'still offline' every 10 seconds. It should clear the timeout and in reality the screen will be unmounted.
const [online, setOnline] = useState(false);
const [loading, setLoading] = useState(false);
const handleChange = () => {
setOnline(!online);
};
const refresh = useCallback(async () => {
setLoading(true);
// in the real screen the following will be assigned to 'online'
// const online = await loadData()
if (!online) {
setLoading(true);
setTimeout(refresh, 10000);
console.log('still offline');
} else {
setLoading(false);
clearTimeout(refresh);
console.log('back on line');
}
}, [online]);
useEffect(() => {
setTimeout(refresh, 10000);
}, [online, refresh]);
return (
<View>
{online ? <Text>Online</Text> : <Text>Offline</Text>}
{loading ? <Text>Loading</Text> : <Text>IDLE</Text>}
<Button title="Go Online" onPress={handleChange} />
</View>
);
Upvotes: 0
Views: 243
Reputation: 3649
If you wanna cancel a previously setup timer you need to store the timer id returned by setTimeout
, you must not pass the setTimeout callback function itself.
const myTimerID = setTimeout(refresh, 10000);
...
clearTimeout(myTimerID)
Take a look at my sample
Upvotes: 1