• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

151
Views
Usar useState con un condicional if dentro de setInterval no funciona
import { useState, useEffect } from "react"; import "./styles.css"; export default function App() { const [progress, setProgress] = useState(0); let progressTimer; function handleTime() { if (progress <= 100) { console.log("Progress: " + progress); setProgress((prevState) => (prevState += 10)); } else { console.log("greater"); clearInterval(progressTimer); } } function handlePlay() { console.log("Timer start"); progressTimer = setInterval(handleTime, 1000); } useEffect(() => { handlePlay(); }); return ( <div className="App"> <h1>Hello CodeSandbox</h1> {progress} <h2>Start editing to see some magic happen!</h2> </div> ); }

Enlace Codesandbox

Resultado deseado: Vaya a 100, contando de 10 en 10 cada 1 segundo. Una vez que llegue a más de 100, apague el temporizador.

Resultado real: simplemente sigue subiendo y subiendo, más rápido que 10 cada 1 segundo.

almost 3 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Problemas

  1. El useEffect para iniciar un intervalo no tiene una matriz de dependencia, por lo que se inició un nuevo intervalo cada vez que se representó el componente. Esto es lo que condujo a los saltos cada vez más grandes.
  2. El progressTimer se vuelve a declarar en cada ciclo de procesamiento, por lo que no hay forma de borrarlo.
  3. La verificación del estado de progress se cierra en el alcance de devolución de llamada cuando se pasa a la devolución de llamada setInterval . Solo estás mirando el valor del estado inicial. En otras palabras, es un recinto rancio.
  4. El uso prevState => (prevState += 10) en la actualización del estado funcional en realidad muta el estado anterior. Deben evitarse todas las mutaciones de estado.

Una solución

  1. Agregue una matriz de dependencias a useEffect para que se ejecute una vez en el montaje del componente. Mueva la lógica handlePlay a la devolución de llamada del efecto para que no haya dependencias externas al montar. No olvide devolver una función de limpieza para borrar los intervalos de ejecución cuando se desmonte el componente.
  2. Almacene el progressTimer como una referencia React para que sea una referencia estable.
  3. Desmezcle la actualización de estado con el efecto secundario de borrar el temporizador. Use un segundo useEffect para verificar cuándo el valor progress actual llega a 100.
  4. En el actualizador de estado, simplemente devuelva el estado anterior más 10, prevState => prevState + 10 como el siguiente valor de estado.

Código

 function App() { const [progress, setProgress] = useState(0); const progressTimer = useRef(); function handleTime() { setProgress((prevState) => prevState + 10); } useEffect(() => { console.log("Progress: " + progress); if (progress >= 100) clearInterval(progressTimer.current); }, [progress]); useEffect(() => { console.log("Timer start"); progressTimer.current = setInterval(handleTime, 1000); return () => clearInterval(progressTimer.current); }, []); return ( <div className="App"> <h1>Hello CodeSandbox</h1> {progress} <h2>Start editing to see some magic happen!</h2> </div> ); }

Edite usando-usestate-with-an-if-conditional-dentro-de-setinterval-isnt-working (bifurcado)

almost 3 years ago · Juan Pablo Isaza Report

0

setInterval con React, cuando se llama en el primer procesamiento, dará como resultado que la devolución de llamada del intervalo tenga un cierre obsoleto de las variables con estado después del primer procesamiento.

En su lugar, usaría setTimeout , de modo que cada vez que se ejecute la devolución de llamada, tendrá el alcance del estado más actualizado.

 const { useState, useEffect } = React; function App() { const [progress, setProgress] = useState(0); function handleTime() { if (progress <= 100) { console.log("Progress: " + progress); setProgress((prevState) => (prevState += 10)); } else { console.log("greater"); } } useEffect(() => { const timerId = setTimeout(handleTime, 1000); return () => clearTimeout(timerId); }); return ( <div className="App"> <h1>Hello CodeSandbox</h1> {progress} <h2>Start editing to see some magic happen!</h2> </div> ); } ReactDOM.render(<App />, document.querySelector('.react'));
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class='react'></div>

almost 3 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error