Tengo una matriz con 3 elementos. Quiero recorrerlo de manera tal que después de 3 segundos se represente el siguiente elemento de la matriz en lugar del anterior y, si se representa el último elemento, debería reiniciarse nuevamente. Es como si después de 3 segundos quisiera mostrar el siguiente elemento en lugar del anterior como un bucle a través de la matriz pero mostrando un elemento a la vez. He intentado el siguiente código para ello.

import React, { useEffect, useState } from 'react';
import './text.css';
const Text = () => {
    var work = ["fighting", "learning", "qwerty"];
    const [seconds, setSeconds] = useState(0);
    useEffect(() => {
        const interval = setInterval(() => {
            if(seconds===2) setSeconds(seconds => seconds = 0);
            else setSeconds(seconds => seconds + 1);
            console.log(seconds);
        }, 3000);
    }, []);

    return (
        <div>
            <h1>{work[seconds]}</h1>
        </div>
    );
}
 
export default Text;

Está procesando elementos uno tras otro con éxito, pero no puede representar nada después del último elemento. También en la consola, el valor de segundos siempre muestra 0.

2
prinzu 24 jun. 2020 a las 07:57

2 respuestas

La mejor respuesta

No estaba obteniendo el valor actualizado second dentro del setInterval.

Además, clearInterval en useEffect.

Demostración de trabajo

Código refactorizado

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(second => (second === 2 ? 0 : second + 1));
    }, 3000);

    return () => clearInterval(interval)
  }, []);

Actualización:

Console.log dentro de la devolución de llamada de setInterval siempre será 0 porque seconds dentro de la devolución de llamada de setInterval es el valor tomado cuando la devolución de llamada se registró con setInterval.

Para ver los valores actualizados de segundo, use otro useEffect con seconds como dependencia.

  useEffect(() => {
    console.log("seconds", seconds);
  }, [seconds]);
1
gdh 24 jun. 2020 a las 05:15

El problema es que el valor de estado inicial está incluido en el alcance de la devolución de llamada y nunca actualiza el valor de estado en el alcance externo, pero la definición de la devolución de llamada externa permite que el estado se actualice. Además, incremente un valor de índice y tome el módulo de la longitud de la matriz para obtener siempre un índice válido.

import React, { useEffect, useState } from "react";

const work = ["fighting", "learning", "qwerty"];

export default function App() {
  const [index, setIndex] = useState(0);

  useEffect(() => {
    const tick = () => setIndex(i => i + 1);

    const id = setInterval(tick, 3000);
    return () => clearInterval(id);
  }, []);

  return (
    <div>
      <h1>{work[index % work.length]}</h1>
    </div>
  );
}

Edit using an interval with react hook

1
Drew Reese 24 jun. 2020 a las 05:22