Sorry, not sure what the best way to word this question is. I've run into a problem where I have an interval which acts as the main loop for my program. I have a complex state object which I need to check constantly and update based on several other state variables. For the sake of simplicity I've reduced the problem state to a counter and a single other state variable.
import React, { useState, useCallback, useEffect } from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
function App(){
const [counter, setCounter] = useState(0);
const [countUp, setCountUp] = useState(true);
const tick = useCallback(()=> {
setCounter((prev)=> prev + (countUp ? 1 : -1));
}
,[]);
useEffect(()=> {
const intervalID = setInterval(tick, 1000);
return () => clearInterval(intervalID);
},[]);
return(
<View style={styles.main}>
<Text>{counter}</Text>
<Button title='switch' onPress={()=> setCountUp(!countUp)}/>
</View>
);
}
const styles = StyleSheet.create({
main: {
flex: 1,
flexDirection: 'column',
height: '100%',
width: '100%',
justifyContent: 'center',
alignItems: 'center'
},
});
export default App;
In this case, I want to swap the DIRECTION of the counter whenever the button is pressed. I can access the current count with the prev
call, but not sure how to do the same when wanting to get the updated countUp
. Keep in mind in my real problem there could be dozens of states such as countUp
, so I'm not sure if there's a better solution that would work for that. Not sure if it's possible, but I'd like to not start and stop the interval as this should be running infinitely.
If you are using TSX, you should see that there is a problem with your effects dependencies.
I fixed that problem and it worked.
This is the correct code:
😀
import React, {useState, useCallback, useEffect} from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';
function App() {
const [counter, setCounter] = useState(0);
const [countUp, setCountUp] = useState(true);
const tick = useCallback(() => {
setCounter(prev => prev + (countUp ? 1 : -1));
}, [countUp]); // dependency 1
useEffect(() => {
const intervalID = setInterval(tick, 1000);
return () => clearInterval(intervalID);
}, [tick]); // dependency 2
return (
<View style={styles.main}>
<Text>{counter}</Text>
<Button title="switch" onPress={() => setCountUp(!countUp)} />
</View>
);
}
const styles = StyleSheet.create({
main: {
flex: 1,
flexDirection: 'column',
height: '100%',
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
});
export default App;
Try that code, it worked for me.
Thanks!
😀