fix : infinite rerenders

This commit is contained in:
GuillaumeSD
2024-02-25 03:02:59 +01:00
parent 7412f708d0
commit 2af25cf4ec
11 changed files with 50 additions and 47 deletions

View File

@@ -1,8 +1,8 @@
# FreeChess
This project is solely a frontend with tools for the chess community.
Freechess is an open-source chess GUI to store, view and analyze your chess games.
It is built with [Next.js](https://nextjs.org/docs), [React](https://react.dev/learn/describing-the-ui) and [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html).
It is built with [Next.js](https://nextjs.org/docs), [React](https://react.dev/learn/describing-the-ui), [Material UI](https://mui.com/material-ui/getting-started/overview/), and [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html).
It is deployed on [Firebase](https://firebase.google.com/docs/hosting), you can see it live [here](https://freechess.web.app).

View File

@@ -7,7 +7,7 @@
"build": "next build",
"start": "next start",
"lint": "next lint && tsc --noEmit",
"deploy": "firebase deploy --project=freechess --only hosting"
"deploy": "firebase deploy --project=freechessproject --only hosting"
},
"dependencies": {
"@emotion/react": "^11.11.1",

View File

@@ -1,42 +1,45 @@
import { Chess, Move } from "chess.js";
import { PrimitiveAtom, useAtom } from "jotai";
import { useCallback } from "react";
export const useChessActions = (chessAtom: PrimitiveAtom<Chess>) => {
const [game, setGame] = useAtom(chessAtom);
const setPgn = (pgn: string) => {
const setPgn = useCallback(
(pgn: string) => {
const newGame = new Chess();
newGame.loadPgn(pgn);
setGame(newGame);
};
},
[setGame]
);
const reset = () => {
const reset = useCallback(() => {
setGame(new Chess());
};
}, [setGame]);
const copyGame = () => {
const copyGame = useCallback(() => {
const newGame = new Chess();
newGame.loadPgn(game.pgn());
return newGame;
};
}, [game]);
const move = (move: {
from: string;
to: string;
promotion?: string;
}): Move | null => {
const makeMove = useCallback(
(move: { from: string; to: string; promotion?: string }): Move | null => {
const newGame = copyGame();
const result = newGame.move(move);
setGame(newGame);
return result;
};
},
[copyGame, setGame]
);
const undo = () => {
const undoMove = useCallback(() => {
const newGame = copyGame();
newGame.undo();
setGame(newGame);
};
}, [copyGame, setGame]);
return { setPgn, reset, move, undo };
return { setPgn, reset, makeMove, undoMove };
};

View File

@@ -18,8 +18,8 @@ import { useRouter } from "next/router";
import { useEffect } from "react";
export default function GameReport() {
const boardActions = useChessActions(boardAtom);
const gameActions = useChessActions(gameAtom);
const { reset: resetBoard } = useChessActions(boardAtom);
const { setPgn: setGamePgn } = useChessActions(gameAtom);
const setEval = useSetAtom(gameEvalAtom);
const setBoardOrientation = useSetAtom(boardOrientationAtom);
const router = useRouter();
@@ -27,12 +27,12 @@ export default function GameReport() {
useEffect(() => {
if (!gameId) {
boardActions.reset();
resetBoard();
setEval(undefined);
setBoardOrientation(true);
gameActions.setPgn(new Chess().pgn());
setGamePgn(new Chess().pgn());
}
}, [gameId, boardActions, gameActions, setEval, setBoardOrientation]);
}, [gameId, setEval, setBoardOrientation, resetBoard, setGamePgn]);
return (
<Grid

View File

@@ -21,7 +21,7 @@ export default function EvaluationBar({ height }: Props) {
useEffect(() => {
const bestLine = currentMove?.eval?.lines[0];
if (!bestLine) return;
if (!bestLine || bestLine.depth < 6) return;
const evalBar = getEvaluationBarValue(bestLine, isWhiteToPlay);
setEvalBar(evalBar);

View File

@@ -20,12 +20,12 @@ export default function Board() {
const boardOrientation = useAtomValue(boardOrientationAtom);
const showBestMoveArrow = useAtomValue(showBestMoveArrowAtom);
const showPlayerMoveArrow = useAtomValue(showPlayerMoveArrowAtom);
const boardActions = useChessActions(boardAtom);
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
const currentMove = useAtomValue(currentMoveAtom);
const onPieceDrop = (source: Square, target: Square): boolean => {
try {
const result = boardActions.move({
const result = makeBoardMove({
from: source,
to: target,
promotion: "q", // TODO: Let the user choose the promotion

View File

@@ -40,9 +40,8 @@ export default function AnalyzePanel() {
engineDepth,
engineMultiPv
);
console.log(newGameEval);
setEval(newGameEval);
setEval(newGameEval);
setEvaluationInProgress(false);
if (gameFromUrl) {

View File

@@ -16,20 +16,20 @@ import { useRouter } from "next/router";
export default function LoadGame() {
const router = useRouter();
const game = useAtomValue(gameAtom);
const gameActions = useChessActions(gameAtom);
const boardActions = useChessActions(boardAtom);
const { setPgn: setGamePgn } = useChessActions(gameAtom);
const { reset: resetBoard } = useChessActions(boardAtom);
const { gameFromUrl } = useGameDatabase();
const setEval = useSetAtom(gameEvalAtom);
const setBoardOrientation = useSetAtom(boardOrientationAtom);
const resetAndSetGamePgn = useCallback(
(pgn: string) => {
boardActions.reset();
resetBoard();
setEval(undefined);
setBoardOrientation(true);
gameActions.setPgn(pgn);
setGamePgn(pgn);
},
[boardActions, gameActions, setEval, setBoardOrientation]
[resetBoard, setGamePgn, setEval, setBoardOrientation]
);
useEffect(() => {

View File

@@ -5,7 +5,7 @@ import { boardAtom, gameAtom } from "../states";
import { useChessActions } from "@/hooks/useChess";
export default function GoToLastPositionButton() {
const boardActions = useChessActions(boardAtom);
const { setPgn: setBoardPgn } = useChessActions(boardAtom);
const game = useAtomValue(gameAtom);
const board = useAtomValue(boardAtom);
@@ -20,7 +20,7 @@ export default function GoToLastPositionButton() {
<IconButton
onClick={() => {
if (isButtonDisabled) return;
boardActions.setPgn(game.pgn());
setBoardPgn(game.pgn());
}}
disabled={isButtonDisabled}
>

View File

@@ -10,7 +10,8 @@ import SaveButton from "./saveButton";
export default function ReviewPanelToolBar() {
const board = useAtomValue(boardAtom);
const boardActions = useChessActions(boardAtom);
const { reset: resetBoard, undoMove: undoBoardMove } =
useChessActions(boardAtom);
const boardHistory = board.history();
@@ -21,7 +22,7 @@ export default function ReviewPanelToolBar() {
<Tooltip title="Reset board">
<Grid>
<IconButton
onClick={() => boardActions.reset()}
onClick={() => resetBoard()}
disabled={boardHistory.length === 0}
>
<Icon icon="ri:skip-back-line" />
@@ -32,7 +33,7 @@ export default function ReviewPanelToolBar() {
<Tooltip title="Go to previous move">
<Grid>
<IconButton
onClick={() => boardActions.undo()}
onClick={() => undoBoardMove()}
disabled={boardHistory.length === 0}
>
<Icon icon="ri:arrow-left-s-line" height={30} />

View File

@@ -5,7 +5,7 @@ import { boardAtom, gameAtom } from "../states";
import { useChessActions } from "@/hooks/useChess";
export default function NextMoveButton() {
const boardActions = useChessActions(boardAtom);
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
const game = useAtomValue(gameAtom);
const board = useAtomValue(boardAtom);
@@ -23,7 +23,7 @@ export default function NextMoveButton() {
const nextMove = game.history({ verbose: true })[nextMoveIndex];
if (nextMove) {
boardActions.move({
makeBoardMove({
from: nextMove.from,
to: nextMove.to,
promotion: nextMove.promotion,