Quiero ejecutar setInterval cuando el usuario haga clic en un botón, toda la lógica está bien para mí, excepto por llamar a clearInterval.

Cuando props.time === 0, quiero ejecutar clearInterval. Sin embargo, encontré que no puedo actualizar props.time. Siempre es igual al valor inicial en la devolución de llamada setInterval.

Soy novato en reaccionar y reaccionar. Encuentro varios gancho como useEffect, useRef que puede ayudarme a resolver el problema. Sin embargo, no puedo entender cómo usarlo. Espero que alguien pueda darme algunos consejos.

Gracias

const [timer, setTimer] = useState(undefined)

const countDown = () => {
  const timerInterval = setInterval(() => {
    if (props.time === 0) clearInterval(timer)

    // execute the logic of "props.time = props.time - 1"
  }, 1000) 
  setTimer(timerInterval)
}

return (
  <button onClick={countDown} />
)
1
bcjohn 15 jul. 2019 a las 11:50

1 respuesta

La mejor respuesta

A ver si esto es lo que estás buscando.

A useRef es el lugar correcto para mantener la referencia setInterval. Será la misma referencia en cada render. No cambiará.

de reaccionar documentos:

https://reactjs.org/docs/hooks-reference.html#useref

useRef

Sin embargo, useRef () es útil para más que el atributo ref. Es útil para mantener cualquier valor mutable similar al de los campos de instancia en las clases.

Esto funciona porque useRef () crea un objeto JavaScript simple. La única diferencia entre useRef () y crear un objeto {current: ...} usted mismo es que useRef le dará el mismo objeto de referencia en cada render.

Tenga en cuenta que useRef no le notifica cuando cambia su contenido. La mutación de la propiedad .current no causa una nueva representación. Si desea ejecutar algún código cuando React adjunta o desconecta una referencia a un nodo DOM, puede utilizar una referencia de devolución de llamada.

function App() {

  const [time, setTime] = React.useState(0);
  const timerRef = React.useRef(null);

  if (time === 0) {
    clearInterval(timerRef.current);
  }
  
  function countDown(startFrom) {
    setTime(startFrom);
    timerRef.current = setInterval(() => {
      setTime((prevState) => prevState -1);
    }, 1000);
  }

  return (
    <React.Fragment>
      <div>Time: {time}</div>
      <button onClick={()=>countDown(3)}>Countdown from 3</button>
      <button onClick={()=>countDown(5)}>Countdown from 5</button>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
1
Community 20 jun. 2020 a las 09:12