React Native timer acting weird (laggy?)
Solution 1:
For each new component rerender, React create a new interval, which results in a memory leak and unexpected behavior.
Let us create a custom hook for interval
import { useEffect, useLayoutEffect, useRef } from 'react'
function useInterval(callback, delay) {
const savedCallback = useRef(callback)
// Remember the latest callback if it changes.
useLayoutEffect(() => {
savedCallback.current = callback
}, [callback])
// Set up the interval.
useEffect(() => {
// Don't schedule if no delay is specified.
// Note: 0 is a valid value for delay.
if (!delay && delay !== 0) {
return
}
const id = setInterval(() => savedCallback.current(), delay)
return () => clearInterval(id)
}, [delay])
}
export default useInterval
Use it in functional component
const Timer = (props) => {
const [workTime, setWorkTime] = useState({v: new Date()});
const [counter, setCounter] = useState(0);
useInterval(()=>{
setCounter( counter + 1);
setWorkTime({v:new Date(counter)});
},1000)
return (
<View>
<Text>{workTime.v.toISOString()}</Text>
</View>
)
}
Here tested result - https://snack.expo.dev/@emmbyiringiro/58cf4b
Solution 2:
As @AKX commented, try wrapping your interval code in a useEffect. Also, return a function from it that clears the interval (the cleanup function).
useEffect(() => {
const interval = setInterval(() => {
setCounter( counter + 1);
setWorkTime({v:new Date(counter)});
}, 1000);
return () => clearInterval(interval);
});
However, using setInterval with 1000 second delay does not yield an accurate clock, if that's what you're going for.