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.

Mantén los números aleatorios consistentes después de un cambio de estado en React.

Estoy haciendo una aplicación Nextjs, y en una página creo un array de números que se mezcla utilizando un número aleatorio. El problema es que cada vez que el estado cambia, el componente se renderiza nuevamente, por lo que el array se vuelve a mezclar. Necesito que la mezcla original se mantenga constante. Aquí está el código relevante:

“`lang-js
export default function Game() {

const { query } = useRouter();
const [cardsFlipped, setCardsFlipped] = useState(
Array(query.tileNumber).fill(false)
);

let counter = query.tileNumber / 2;

let iconSet = […Array(counter).keys()];
while (counter > 0) {
const index = Math.floor(Math.random() * iconSet.length);
tiles.push(iconSet.splice(index, 1));
counter–;
}

const tileOrder = tiles.concat(tiles).sort((a, b) => 0.5 – Math.random());

const handleFlip = (index) => {
if (cardsFlipped[index] === false) {
setCardsFlipped((prev) =>
prev.map((el, i) => {
if (i === index) {
return true;
}
return el;
})
);

setTimeout(() => {
setCardsFlipped((prev) =>
prev.map((el, i) => {
if (i === index) {
return false;
}
return el;
})
);
}, query.tileTransition * 1000);
}

};

let cards = tileOrder.map((e, i) => (

{
handleFlip(i);
}}
/>


));
return (

{cards}

);
}

Pensé en convertirlo en una clase y tener un constructor, pero luego obtengo un error de que useRouter no se puede utilizar en clases.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para solucionar este problema, puedes utilizar el gancho useMemo para crear un valor memorizado del arreglo tileOrder. De esta manera, el arreglo solo se desordenará una vez y se utilizará el mismo orden en cada renderización.

    Aquí tienes un ejemplo de cómo puedes utilizar useMemo en tu código:

    export default function Game() {
    
      const { query } = useRouter();
      const [cardsFlipped, setCardsFlipped] = useState(
        Array(query.tileNumber).fill(false)
      );
    
      const tileOrder = useMemo(() => {
        let counter = query.tileNumber / 2;
        let iconSet = [...Array(counter).keys()];
        let tiles = [];
    
        while (counter > 0) {
          const index = Math.floor(Math.random() * iconSet.length);
          tiles.push(iconSet.splice(index, 1));
          counter--;
        }
    
        return tiles.concat(tiles).sort((a, b) => 0.5 - Math.random());
      }, [query.tileNumber]);
    
      const handleFlip = (index) => {
        if (cardsFlipped[index] === false) {
          setCardsFlipped((prev) =>
            prev.map((el, i) => {
              if (i === index) {
                return true;
              }
              return el;
            })
          );
    
          setTimeout(() => {
            setCardsFlipped((prev) =>
              prev.map((el, i) => {
                if (i === index) {
                  return false;
                }
                return el;
              })
            );
          }, query.tileTransition * 1000);
        }
      };
    
      let cards = tileOrder.map((e, i) => (
        <reactcardflip isflipped="{cardsFlipped[i]}" flipdirection="horizontal" key="{"card"" +="" i="" +="" "-"="" +="" e}="">
          <card iconset="{2}" index="{50}" callback="{()" ==""> {
              handleFlip(i);
            }}
          />
          <card iconset="{parseInt(query.icons)}" index="{e}" callback="{handleFlip}"></card>
        </card></reactcardflip>
      ));
    
      return (<div>{cards}</div>);
    }
    

    En este ejemplo, el arreglo tileOrder se crea utilizando el gancho useMemo con query.tileNumber como dependencia. Esto significa que el arreglo tileOrder solo se volverá a calcular cuando query.tileNumber cambie.

    Ahora, el arreglo tileOrder mantendrá su orden de desordenamiento en cada renderización, y no es necesario convertir el componente en una clase.

Comments are closed.