Estoy probando React Native implementando un temporizador simple. Al ejecutar el código, el conteo funciona perfectamente durante los primeros 6 segundos, luego la aplicación comienza a actuar de manera extraña.
Aquí está el código, que puedes probar en esta Expo Snack
import React, { useEffect, useState } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { Button } from 'react-native'; const App = () => { return ( <View style={styles.container}> <Timer></Timer> </View> ); } const Timer = (props) => { const [workTime, setWorkTime] = useState({v: new Date()}); const [counter, setCounter] = useState(0); setInterval(() => { setCounter( counter + 1); setWorkTime({v:new Date(counter)}); }, 1000); return ( <View> <Text>{workTime.v.toISOString()}</Text> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, }); export default App;Para cada nuevo renderizado de componente, React crea un nuevo intervalo, lo que resulta en una pérdida de memoria y un comportamiento inesperado.
Vamos a crear un gancho personalizado para el intervalo.
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Úselo en el componente funcional
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> ) }Aquí el resultado probado: https://snack.expo.dev/@emmbyiringiro/58cf4b
Como comentó @AKX, intente envolver su código de intervalo en un useEffect. Además, devuelva una función que borre el intervalo (la función de limpieza).
useEffect(() => { const interval = setInterval(() => { setCounter( counter + 1); setWorkTime({v:new Date(counter)}); }, 1000); return () => clearInterval(interval); });Sin embargo, usar setInterval con 1000 segundos de retraso no produce un reloj preciso, si eso es lo que busca.