React 状态改变后保持随机数一致

Keep random numbers consistent after state change in React

我正在制作一个 Nextjs 应用程序,并在一个页面上创建了一个数字数组,该数组使用随机数进行混洗。问题是每次状态改变时,组件都会被渲染,所以数组会重新洗牌。我需要原始洗牌以保持一致。这是相关代码:

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) => (
    <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} />
    </ReactCardFlip>
  ));
 return (<div>{cards}</div>);
}

我想把它转换成 class,并有一个构造函数,但后来我得到一个错误,说 useRouter 不能在 classes 中使用。

你只需要将你的逻辑包装在一个 useEffect 中,就像这样:

export default function Test() {
  const { query } = useRouter();
  const [cardsFlipped, setCardsFlipped] = useState(
    Array(query.tileNumber).fill(false)
  );
  const [tileOrder, setTileOrder] = useState([]);

  useEffect(() => {
    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--;
    }

    setTileOrder(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) => (
    <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} />
    </ReactCardFlip>
  ));
  return <div>{cards}</div>;
}