我正在尝试制作这款记忆卡游戏。 它工作得很好,但底部的尝试却以一种奇怪的方式反作用。事实上,它有时会增加 1,有时会增加 2。 为什么会发生这种情况?
import { useState } from 'react';
import Button from "./Button";
const possibleElements = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];
function randomNumber() {
const randIndex = Math.floor(Math.random() * possibleElements.length);
const randomNumber = possibleElements[randIndex];
possibleElements.splice(randIndex, 1);
return randomNumber;
}
const gameTable = [
[randomNumber(), randomNumber(), randomNumber(), randomNumber()],
[randomNumber(), randomNumber(), randomNumber(), randomNumber()],
[randomNumber(), randomNumber(), randomNumber(), randomNumber()],
[randomNumber(), randomNumber(), randomNumber(), randomNumber()]
];
export default function GameBoard() {
const [selection, setSelection] = useState([]);
const [coupledElements, setCoupledElements] = useState([]);
const [isEnabled, setIseEnabled] = useState(true);
const [attempts, setAttempts] = useState(0);
function sortCoupledElements(selection) {
if (selection[0].value === selection[1].value) {
setCoupledElements((prevCoupledElements) => {
const newCoupledElements = [...prevCoupledElements, selection[0].index, selection[1].index];
return newCoupledElements;
})
}
}
function whenClicked(index, value) {
setSelection((prevSelection) => {
const newSelection = [...prevSelection, { index, value }];
if (newSelection.length === 2) {
setAttempts((prevAttempts) => (prevAttempts + 1));
setIseEnabled(false);
sortCoupledElements(newSelection);
setTimeout(() => {
setSelection([]);
setIseEnabled(true);
}, 1000);
}
return newSelection;
})
}
return (
<main>
<div className="game-board">
<ol className="row">
{gameTable.map((row, rowIndex) => (
<li key={rowIndex}>
<ol className="column">
{row.map((value, colIndex) => {
const elementIndex = rowIndex * 4 + colIndex
return (
<li key={colIndex}>
<Button
isSelected={selection.some((element) => (element.index === elementIndex))}
ifClicked={whenClicked}
isCoupled={coupledElements.includes(elementIndex)}
isEnabled={isEnabled}
index={elementIndex}
value={value} />
</li>
)
})}
</ol>
</li>
))}
</ol>
</div>
<div id="attempts">
<h3>{attempts} attempts!</h3>
</div>
</main>
)
}
提前谢谢您!
我认为这可能是由于 setAttempts 重新渲染 setSelection 重新渲染内的组件造成的。 问题是当selection.length为2时必须调用它。 我尝试用一个函数来做到这一点:
function increaseAttempts() {
setAttempts((prevAttempts) => (prevAttempts +1))
}
并在
if (newSelection.length ===2)
语句之后的 setSelection 调用中调用此函数,但在这种情况下,发生了另一件奇怪的事情,即没有按钮将其 isSelected
属性保持等于 true 。
您不应该在另一个状态变量的更新函数内更新变量的状态。使用
useEffect
钩子来执行此类任务,添加另一个变量作为其依赖项。
function whenClicked(index, value) {
setSelection((prevSelection) => {
const newSelection = [...prevSelection, { index, value }];
// do not update any other state here
return newSelection;
})
}
useEffect(()=>{
if (selection.length === 2) {
setAttempts((prevAttempts) => (prevAttempts + 1));
setIseEnabled(false);
sortCoupledElements(newSelection);
setTimeout(() => {
setSelection([]);
setIseEnabled(true);
}, 1000);
}
}, [selection.length])