es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Reaccionar: Eliminando el primer elemento en el array de useState después de un evento (o temporizador)

Tengo una función que completa una matriz de objetos de useState: coches que aparecen en la parte izquierda de la pantalla y se animan hasta que desaparecen de la pantalla. Después de que el coche desaparezca de la pantalla, quiero que se eliminen de la matriz del estado, para poder tener un bucle infinito de coches aleatorios (a velocidades aleatorias). Los objetos están etiquetados con claves indexadas en 0.

En este momento, estoy intentando un temporizador de 9 segundos para eliminar los coches, pero esto solo vacía toda la matriz después de 9 segundos. ¡Muchas gracias por leer/ayudar!

“`javascript
const getRandomNumber = (min: number, max: number) => {
return Math.random() * (max – min) + min;
};

const getRandomNumberToString = (min: number, max: number) => {
const result = Math.random() * (max – min) + min;
return result.toString();
};

const CarLeft = styled.div<code>animation-duration: ${getRandomNumberToString(2, 9)}s;</code>;

const carListDay = [car1, car2, car3, car4, car5, car6];

function Traffic() {
const [carsOnTheLeft, setCarsOnTheLeft] = useState<any>([]);
const timeout = useRef<any>();

useEffect(() => {
timeout.current = setTimeout(() => {
if (carsOnTheLeft.length < 30)
setCarsOnTheLeft([
…carsOnTheLeft,
<carleft key="{carsOnTheLeft.length}" classname="car__left">
<img src="{carListDay[Math.floor(Math.random()" *="" carlistday.length)]}="" alt="">
</carleft>,
]);
else clearTimeout(timeout.current);
}, getRandomNumber(500, 5000));
console.log(carsOnTheLeft);

<pre><code>setTimeout(() => {
const name = "0";
setCarsOnTheLeft(carsOnTheLeft.filter((item: any) => item.name !== name));
}, 9000);

return () => {
clearTimeout(timeout.current);
};
</code></pre>

}, [carsOnTheLeft]);

return

<div classname="traffic__container">{carsOnTheLeft}</div>

;
}

export default Traffic;
“`

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para eliminar los autos que se han salido de la pantalla del array useState, puedes agregar un efecto (useEffect) con una función de limpieza que elimine los autos en función de su posición.

    En primer lugar, necesitarías agregar una variable de estado para llevar un seguimiento de las posiciones de los autos:

    const [carPositions, setCarPositions] = useState<any>([]);

    Esta variable será un arreglo de objetos que contiene la posición de cada auto. Cuando se agrega un auto al arreglo carsOnTheLeft, puedes agregar un objeto de posición correspondiente a carPositions:

    setCarPositions([
      ...carPositions,
      {
        key: carsOnTheLeft.length,
        position: 0,
      },
    ]);
    

    Aquí, la clave (key) corresponde a la clave del auto en el arreglo carsOnTheLeft y position representa la posición actual del auto.

    Para actualizar la posición de los autos, puedes agregar un setTimeout dentro del efecto (useEffect) que actualice la variable position de cada objeto de posición de auto:

    timeout.current = setTimeout(() => {
      if (carsOnTheLeft.length < 30) {
        const newCars = [
          ...carsOnTheLeft,
          <carleft key="{carsOnTheLeft.length}" classname="car__left" onanimationend="{()" ==""> {
              const name = carsOnTheLeft.length.toString();
              setCarsOnTheLeft(carsOnTheLeft.filter((item: any) => item.key !== name));
              setCarPositions(carPositions.filter((item: any) => item.key !== name));
            }}
          >
            <img src="{carListDay[Math.floor(Math.random()" *="" carlistday.length)]}="" alt="">
          </carleft>,
        ];
        setCarsOnTheLeft(newCars);
        setCarPositions(
          carPositions.map((item: any) => ({
            ...item,
            position: item.position + 1,
          }))
        );
      } else clearTimeout(timeout.current);
    }, getRandomNumber(500, 5000));
    

    Aquí, se agrega la función onAnimationEnd a cada elemento de auto. Cuando la animación termine, esta función eliminará el auto correspondiente y su posición del arreglo respectivo filtrándolos por la clave.

    Ahora, puedes agregar otro efecto (useEffect) que verifique si algún auto se ha salido de la pantalla y lo elimine de los arreglos carsOnTheLeft y carPositions:

    useEffect(() => {
      setCarPositions(
        carPositions.filter((item: any) => {
          if (item.position > window.innerWidth) {
            const name = item.key.toString();
            setCarsOnTheLeft(carsOnTheLeft.filter((item: any) => item.key !== name));
            return false;
          } else return true;
        })
      );
    }, [carsOnTheLeft, carPositions]);
    

    Aquí, el arreglo carPositions se filtra en función de la condición de que la posición sea mayor que window.innerWidth, que representa el ancho de la pantalla. Si un objeto de posición no cumple esta condición, se eliminará el auto correspondiente del arreglo carsOnTheLeft y se eliminará el objeto de posición del arreglo carPositions.

    Por último, puedes eliminar el temporizador de 9 segundos para eliminar todos los autos y mantener el efecto (useEffect) que elimina los autos en función de su posición:

    // setTimeout(() => {
    //   const name = "0";
    //   setCarsOnTheLeft(carsOnTheLeft.filter((item: any) => item.name !== name));
    // }, 9000);
    

    Con estos cambios, tendrás un bucle infinito de autos aleatorios que se mueven por la pantalla a velocidades aleatorias y se eliminan cuando salen de la pantalla.

Comments are closed.