#reactjs #react-hooks #use-effect
Вопрос:
Я пытаюсь разработать игру в крестики — нолики с использованием React и застрял на базовом шаге, т. Е. Я хочу, чтобы первый ход был X, а следующий-O и так далее.
У меня есть приведенный ниже код. Итак, я пытаюсь инициализировать состояние «данные» (что должно быть установлено) сначала на X, а затем установить состояние «Следующий выбор» в обратном порядке с помощью:
nxtChoice = (data === "X") ? "O" : "X";
setNextChoice(nxtChoice);
Теперь, похоже, проблема в том, что квадратный компонент снова монтируется, а затем состояние «Первое перемещение» устанавливается в значение true каждый раз, когда возникает проблема, т. Е. Невозможность переключения между X и O.
В чем логическая проблема с приведенным выше кодом и как я могу не сбрасывать firstMove каждый раз?
function Square(props) {
const [firstMove, setFirstMove] = useState(true);
let [nextChoice, setNextChoice] = React.useState("X");
let [data, setData] = React.useState("");
useEffect(() => {
if (data !== "") {
nxtChoice = (data === "X") ? "O" : "X";
setNextChoice(nxtChoice);
}
}, [data]);
const squareClicked = () => {
let nxtChoice = firstMove ? "X" : nextChoice;
setData(nxtChoice);
setFirstMove(false);
};
return (
<div className="square" style={squareStyle} onClick={squareClicked}>
{data}
</div>
);
}
class Board extends React.Component {
render() {
return (
<div style={containerStyle} className="gameBoard">
<div id="statusArea" className="status" style={instructionsStyle}>
Next player: <span>X</span>
</div>
<div id="winnerArea" className="winner" style={instructionsStyle}>
Winner: <span>None</span>
</div>
<button style={buttonStyle}>Reset</button>
<div style={boardStyle}>
<div className="board-row" style={rowStyle}>
<Square row={"1"} column={"1"} />
<Square row={"1"} column={"2"} />
<Square row={"1"} column={"3"} />
</div>
<div className="board-row" style={rowStyle}>
<Square row={"2"} column={"1"} />
<Square row={"2"} column={"2"} />
<Square row={"2"} column={"3"} />
</div>
<div className="board-row" style={rowStyle}>
<Square row={"3"} column={"1"} />
<Square row={"3"} column={"2"} />
<Square row={"3"} column={"3"} />
</div>
</div>
</div>
);
}
}
Код также можно увидеть на
https://codesandbox.io/s/rough-glade-c1ssw?file=/src/App.js:1307-3349
Комментарии:
1. Вы заметили, что некоторые переменные в вашем примере не определены, возможно, вам следует заранее исправить ошибки lint
2. да, планируйте сделать это во время рефакторинга всего кода…
Ответ №1:
То, что вы видите , происходит, это не Square
то, что компонент перемонтирован, но для каждого экземпляра Square
он имеет отдельное индивидуально рабочее состояние.
Для того, чтобы игра работала, эти состояния должны быть перенесены в Board
компонент и переданы каждому из Square
компонентов.
Комментарии:
1. Итак, должен ли мыслительный процесс быть похож на то, что состояние всегда должно находиться на самом верху иерархии и стекать вниз к дочерним компонентам…что-то вроде DDAU ? Любое оправдание или обоснование того же было бы действительно полезно…
2. Если вы хотите, чтобы ваши компоненты совместно использовали этот единственный источник информации, то да.
Ответ №2:
Существует так много проблем…
Главное из них заключается в том, что состояние игры хранится в квадратах, а не в компоненте приложения.