Estoy tratando de implementar un temporizador simple que solo cuenta continuamente cada segundo. Estoy usando reaccionar para representar el resultado. El código tiene solo unas pocas líneas y tiene sentido por lo que he estado leyendo. Agrega y renderiza correctamente durante los primeros 6 segundos; sin embargo, simplemente comienza a mostrar números aleatorios después del 7 u 8, O el temporizador se vuelve erróneo y se actualiza cada segundo aleatorio. Mi código es el siguiente, ¿estoy haciendo algo mal? ¡Gracias!
import React, {useState} from 'react'; function App() { const [count, setCount] = useState(0); setInterval(()=>{setCount(count + 1)}, 1000) return ( <div className="welcome"> {count} </div> ); } export default App;eso porque comienza uno nuevo cada vez que el componente se vuelve a renderizar, use esto en su lugar
import React, {useState} from 'react'; function App() { const [count, setCount] = useState(0); const timer = useRef(null); useEffect(() => { timer.current = setInterval(()=>{setCount(count + 1)}, 1000); return () => { if(timer.current !== null) clearInterval(timer.current); }; }, []); return ( <div className="welcome"> {count} </div> ); } export default App;Su código tiene algunos problemas, al igual que las otras respuestas. Se pueden resumir en tres puntos:
Si desea usar Interval o Timeout (o cualquier otro detector de eventos), debe hacerlo dentro de un useEffect , por lo que no agregará un nuevo detector en cada procesamiento.
Si usa un useEffect para ello, deberá limpiar Interval/Timeout (o cualquier otro oyente) para evitar pérdidas de memoria.
Podemos evitar usar la variable de count dentro de la matriz de dependencias usando setCount(oldCount => oldCount + 1) . Citando la documentación de React :
Si el nuevo estado se calcula utilizando el estado anterior, puede pasar una función a setState. La función recibirá el valor anterior y devolverá un valor actualizado.
Si ignora el paso 3 usando el count como una dependencia de enlace, creará y limpiará un Intervalo en cada renderizado; esto no es necesario.
Si decide usar simplemente setCount(count + 1) sin agregarlo a la matriz de dependencia, está usando ganchos de forma incorrecta, count siempre tendrá el mismo valor (el inicial).
Agregué un botón para forzar una nueva representación en el ejemplo a continuación para mostrar que el conteo continúa como se esperaba.
function App() { const [count, setCount] = React.useState(0); const [forced, setForced] = React.useState(0); React.useEffect(() => { // Store the interval id in a const, so you can cleanup later const intervalId = setInterval(() => { setCount(oldCount => oldCount + 1); }, 1000); return () => { // Since useEffect dependency array is empty, this will be called only on unmount clearInterval(intervalId); }; }, []); function forceRerender() { setForced(oldForced => oldForced + 1); } return ( <div> <p>{count} seconds</p> <p>Forced re-renders: {forced}</p> <button onClick={forceRerender}>Force a re-render</button> </div> ); } ReactDOM.render(<App />, document.querySelector('#app')); <div id="app"></div> <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>La llamada setInterval debe colocarse dentro de un useEffect y también debe realizarse la limpieza:
import React, { useState, useEffect, useRef } from "react"; function App() { const [count, setCount] = useState(0); const ref = useRef(); useEffect(() => { ref.current = setInterval(() => { setCount(count + 1); }, 1000); return () => { clearInterval(ref.current); }; }, [count]); return <div className="welcome">{count}</div>; } export default App;