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>;
}
我正在制作一个 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>;
}