# #javascript #reactjs #firebase #next.js
Вопрос:
Я создаю многопользовательскую онлайн-игру в крестики-нолики с firebase и next-js. В этой игре я хочу проверить ход игроков, т. е. Если следующий ход будет «O», то «X» не сможет изменить ни одну плитку и ее расположение. Фиксированный ход кулака всегда «X» в игре, и я создал переменную состояния под названием isNextO
const [isNextO, setIsNextO] = useState("yes");
что изначально означает «да», но когда «О» выполняет свой ход, он меняет состояние на «нет» следующим образом
var isTurn = isNextO === "yes" ? "no" : "yes";
setIsNextO(isTurn);
но когда я проверяю isNextO внутри оператора if, он всегда принимает значение true
if (isNextO === "yes") {
console.log("Next is O");
if (host == 1) {
console.log("Host is playing");
return;
} else if (guest == 1) {
var isTurn = isNextO === "yes" ? "no" : "yes";
setIsNextO(isTurn);
console.log(`Is Next O: ${isTurn} `);
}
}
даже если значение isNextO равно «нет», приведенный выше оператор main if принимает значение true, и в результате мой хост не может сыграть ни одного хода. В эффекте использования есть некоторые операции с базой данных (базой данных в реальном времени). Ниже приведен полный код файла. Любая помощь будет признательна.
import React, { useState } from "react";
import Square from "./Square";
import styles from "../styles/Game.module.css";
import firebase from "firebase/app";
import "firebase/database";
const database = firebase.database();
const Board = ({ code, host, getUsers, guest }) => {
const reference = database.ref(`/game/${code}`);
const [squares, setSquares] = useState(Array(9).fill(null));
const [winner, setWinner] = useState("");
const [isNextO, setIsNextO] = useState("yes");
const sq = squares;
const handleClick = (i) => {
if (calculateWinner(squares) || squares[i]) {
return;
}
if (isNextO === "yes") {
console.log("Next is O");
if (host == 1) {
console.log("Host is playing");
return;
} else if (guest == 1) {
var isTurn = isNextO === "yes" ? "no" : "yes";
setIsNextO(isTurn);
console.log(`Is Next O: ${isTurn} `);
}
}
var move = "";
if (host == 1) {
move = "X";
} else if (guest == 1) {
move = "O";
}
// setisNextO(!isNextO);
// reference
// .once("value")
// .then((snapshot) => {
// const fetchedData = snapshot.val();
// const newMovesFetched = fetchedData.moves;
// if (host === true) console.log("this is X");
// else console.log("this is O");
// console.log(`Move: ${move}`);
// newMovesFetched.push({
// move,
// index: i,
// });
// reference
// .update({
// moves: newMovesFetched,
// })
// .then((res) => {
// setisNextO(!isNextO);
// })
// .catch((e) => console.log(e));
// })
// .catch((e) => console.log(e));
};
if (!winner) {
const winn = calculateWinner(squares);
if (winn) {
reference
.update({
winner: winn,
})
.then(() => {
setWinner(calculateWinner(squares));
})
.catch((e) => console.log(e));
}
}
React.useEffect(() => {
const change = database.ref(`/game/${code}`).on("value", (snap) => {
const data = snap.val();
if (data.guest amp;amp; data.host) {
const user = {
guest: data.guest,
host: data.host,
winner: data.winner,
};
getUsers(user);
}
const squares = sq.slice();
const moves = data.moves;
for (let i = 0; i < data.moves.length; i ) {
const index = moves[i].index;
const move = moves[i].move;
squares[index] = move;
console.log(moves[i]);
}
setSquares(squares);
});
return () => database.ref(`/game/${code}`).off("value", change);
}, []);
const renderSquare = (i) => {
return <Square value={squares[i]} onClick={() => handleClick(i)} />;
};
return (
<>
{winner ? (
<h1>{winner}</h1>
) : (
<div className={styles.board}>
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
)}
</>
);
};
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i ) {
const [a, b, c] = lines[i];
if (squares[a] amp;amp; squares[a] === squares[b] amp;amp; squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
export default Board;
Примечание: Комментируемая часть предназначена для операций с базой данных, основанных на ходах, сыгранных игроками, и комментируется таким образом, чтобы избежать обширных операций чтения-записи во время тестирования кода.
Комментарии:
1.
setState
вступает в силу только при следующем рендеринге overreacted.io/a-complete-guide-to-useeffect/…2. @Надя Чибрикова, можете ли вы предложить какое-либо решение? Журнал консоли после
setIsNextO
корректного отображения состояния3. Вы можете использовать
isTurn
вместоisNextO
внутри обработчика (после того, как вы позвонилиsetIsNextO(isTurn);
, вы знаете, что в конечном итоге этоisNextO
будет иметь значениеisTurn
)4. Кроме того, у React есть официальный учебник по этой же игре, возможно, вам захочется взглянуть reactjs.org/tutorial/tutorial.html
5. Игра в этом уроке предназначена для локальной игры, но я пытаюсь создать ее с помощью firebase, чтобы два игрока могли играть онлайн