From 2af25cf4ec82983a18457df58de41176fdf1550e Mon Sep 17 00:00:00 2001 From: GuillaumeSD Date: Sun, 25 Feb 2024 03:02:59 +0100 Subject: [PATCH] fix : infinite rerenders --- README.md | 4 +- package.json | 2 +- src/hooks/useChess.ts | 47 ++++++++++--------- src/pages/index.tsx | 10 ++-- src/sections/analysis/board/evaluationBar.tsx | 2 +- src/sections/analysis/board/index.tsx | 4 +- .../reviewPanelHeader/analyzePanel.tsx | 3 +- .../analysis/reviewPanelHeader/loadGame.tsx | 10 ++-- .../goToLastPositionButton.tsx | 4 +- .../analysis/reviewPanelToolbar/index.tsx | 7 +-- .../reviewPanelToolbar/nextMoveButton.tsx | 4 +- 11 files changed, 50 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 937d7f9..75845d3 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/package.json b/package.json index 3a25e96..800a620 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/hooks/useChess.ts b/src/hooks/useChess.ts index fe0e6c3..c417aad 100644 --- a/src/hooks/useChess.ts +++ b/src/hooks/useChess.ts @@ -1,42 +1,45 @@ import { Chess, Move } from "chess.js"; import { PrimitiveAtom, useAtom } from "jotai"; +import { useCallback } from "react"; export const useChessActions = (chessAtom: PrimitiveAtom) => { const [game, setGame] = useAtom(chessAtom); - const setPgn = (pgn: string) => { - const newGame = new Chess(); - newGame.loadPgn(pgn); - setGame(newGame); - }; + 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 newGame = copyGame(); - const result = newGame.move(move); - setGame(newGame); + const makeMove = useCallback( + (move: { from: string; to: string; promotion?: string }): Move | null => { + const newGame = copyGame(); + const result = newGame.move(move); + setGame(newGame); - return result; - }; + 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 }; }; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index fb044f2..6a50185 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -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 ( { const bestLine = currentMove?.eval?.lines[0]; - if (!bestLine) return; + if (!bestLine || bestLine.depth < 6) return; const evalBar = getEvaluationBarValue(bestLine, isWhiteToPlay); setEvalBar(evalBar); diff --git a/src/sections/analysis/board/index.tsx b/src/sections/analysis/board/index.tsx index 75412f9..4f02c42 100644 --- a/src/sections/analysis/board/index.tsx +++ b/src/sections/analysis/board/index.tsx @@ -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 diff --git a/src/sections/analysis/reviewPanelHeader/analyzePanel.tsx b/src/sections/analysis/reviewPanelHeader/analyzePanel.tsx index 7ccc042..01f9180 100644 --- a/src/sections/analysis/reviewPanelHeader/analyzePanel.tsx +++ b/src/sections/analysis/reviewPanelHeader/analyzePanel.tsx @@ -40,9 +40,8 @@ export default function AnalyzePanel() { engineDepth, engineMultiPv ); - console.log(newGameEval); - setEval(newGameEval); + setEval(newGameEval); setEvaluationInProgress(false); if (gameFromUrl) { diff --git a/src/sections/analysis/reviewPanelHeader/loadGame.tsx b/src/sections/analysis/reviewPanelHeader/loadGame.tsx index e50c16c..0d4cc84 100644 --- a/src/sections/analysis/reviewPanelHeader/loadGame.tsx +++ b/src/sections/analysis/reviewPanelHeader/loadGame.tsx @@ -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(() => { diff --git a/src/sections/analysis/reviewPanelToolbar/goToLastPositionButton.tsx b/src/sections/analysis/reviewPanelToolbar/goToLastPositionButton.tsx index 9c218ee..db13e2b 100644 --- a/src/sections/analysis/reviewPanelToolbar/goToLastPositionButton.tsx +++ b/src/sections/analysis/reviewPanelToolbar/goToLastPositionButton.tsx @@ -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() { { if (isButtonDisabled) return; - boardActions.setPgn(game.pgn()); + setBoardPgn(game.pgn()); }} disabled={isButtonDisabled} > diff --git a/src/sections/analysis/reviewPanelToolbar/index.tsx b/src/sections/analysis/reviewPanelToolbar/index.tsx index bd4b067..c3d2288 100644 --- a/src/sections/analysis/reviewPanelToolbar/index.tsx +++ b/src/sections/analysis/reviewPanelToolbar/index.tsx @@ -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() { boardActions.reset()} + onClick={() => resetBoard()} disabled={boardHistory.length === 0} > @@ -32,7 +33,7 @@ export default function ReviewPanelToolBar() { boardActions.undo()} + onClick={() => undoBoardMove()} disabled={boardHistory.length === 0} > diff --git a/src/sections/analysis/reviewPanelToolbar/nextMoveButton.tsx b/src/sections/analysis/reviewPanelToolbar/nextMoveButton.tsx index 535b449..a9f44e1 100644 --- a/src/sections/analysis/reviewPanelToolbar/nextMoveButton.tsx +++ b/src/sections/analysis/reviewPanelToolbar/nextMoveButton.tsx @@ -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,