fix : board perf optimization
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
|||||||
Square,
|
Square,
|
||||||
} from "react-chessboard/dist/chessboard/types";
|
} from "react-chessboard/dist/chessboard/types";
|
||||||
import { useChessActions } from "@/hooks/useChessActions";
|
import { useChessActions } from "@/hooks/useChessActions";
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useMemo, useRef, useState } from "react";
|
||||||
import { Color, MoveClassification } from "@/types/enums";
|
import { Color, MoveClassification } from "@/types/enums";
|
||||||
import { Chess } from "chess.js";
|
import { Chess } from "chess.js";
|
||||||
import { getSquareRenderer } from "./squareRenderer";
|
import { getSquareRenderer } from "./squareRenderer";
|
||||||
@@ -64,10 +64,11 @@ export default function Board({
|
|||||||
const boardHue = useAtomValue(boardHueAtom);
|
const boardHue = useAtomValue(boardHueAtom);
|
||||||
|
|
||||||
const gameFen = game.fen();
|
const gameFen = game.fen();
|
||||||
|
const [previousFen, setPreviousFen] = useState(gameFen);
|
||||||
useEffect(() => {
|
if (gameFen !== previousFen) {
|
||||||
|
setPreviousFen(gameFen);
|
||||||
setClickedSquares([]);
|
setClickedSquares([]);
|
||||||
}, [gameFen, setClickedSquares]);
|
}
|
||||||
|
|
||||||
const isPiecePlayable = useCallback(
|
const isPiecePlayable = useCallback(
|
||||||
({ piece }: { piece: string }): boolean => {
|
({ piece }: { piece: string }): boolean => {
|
||||||
@@ -78,11 +79,8 @@ export default function Board({
|
|||||||
[canPlay, game]
|
[canPlay, game]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onPieceDrop = (
|
const onPieceDrop = useCallback(
|
||||||
source: Square,
|
(source: Square, target: Square, piece: string): boolean => {
|
||||||
target: Square,
|
|
||||||
piece: string
|
|
||||||
): boolean => {
|
|
||||||
if (!isPiecePlayable({ piece })) return false;
|
if (!isPiecePlayable({ piece })) return false;
|
||||||
|
|
||||||
const result = playMove({
|
const result = playMove({
|
||||||
@@ -92,9 +90,12 @@ export default function Board({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return !!result;
|
return !!result;
|
||||||
};
|
},
|
||||||
|
[isPiecePlayable, playMove]
|
||||||
|
);
|
||||||
|
|
||||||
const resetMoveClick = (square?: Square | null) => {
|
const resetMoveClick = useCallback(
|
||||||
|
(square?: Square | null) => {
|
||||||
setMoveClickFrom(square ?? null);
|
setMoveClickFrom(square ?? null);
|
||||||
setMoveClickTo(null);
|
setMoveClickTo(null);
|
||||||
setShowPromotionDialog(false);
|
setShowPromotionDialog(false);
|
||||||
@@ -104,9 +105,12 @@ export default function Board({
|
|||||||
} else {
|
} else {
|
||||||
setPlayableSquares([]);
|
setPlayableSquares([]);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[setMoveClickFrom, setMoveClickTo, setPlayableSquares, game]
|
||||||
|
);
|
||||||
|
|
||||||
const handleSquareLeftClick = (square: Square, piece?: string) => {
|
const handleSquareLeftClick = useCallback(
|
||||||
|
(square: Square, piece?: string) => {
|
||||||
setClickedSquares([]);
|
setClickedSquares([]);
|
||||||
|
|
||||||
if (!moveClickFrom) {
|
if (!moveClickFrom) {
|
||||||
@@ -140,29 +144,41 @@ export default function Board({
|
|||||||
});
|
});
|
||||||
|
|
||||||
resetMoveClick(result ? undefined : square);
|
resetMoveClick(result ? undefined : square);
|
||||||
};
|
},
|
||||||
|
[
|
||||||
|
game,
|
||||||
|
isPiecePlayable,
|
||||||
|
moveClickFrom,
|
||||||
|
playMove,
|
||||||
|
resetMoveClick,
|
||||||
|
setClickedSquares,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
const handleSquareRightClick = (square: Square) => {
|
const handleSquareRightClick = useCallback(
|
||||||
|
(square: Square) => {
|
||||||
setClickedSquares((prev) =>
|
setClickedSquares((prev) =>
|
||||||
prev.includes(square)
|
prev.includes(square)
|
||||||
? prev.filter((s) => s !== square)
|
? prev.filter((s) => s !== square)
|
||||||
: [...prev, square]
|
: [...prev, square]
|
||||||
);
|
);
|
||||||
};
|
},
|
||||||
|
[setClickedSquares]
|
||||||
|
);
|
||||||
|
|
||||||
const handlePieceDragBegin = (_: string, square: Square) => {
|
const handlePieceDragBegin = useCallback(
|
||||||
|
(_: string, square: Square) => {
|
||||||
resetMoveClick(square);
|
resetMoveClick(square);
|
||||||
};
|
},
|
||||||
|
[resetMoveClick]
|
||||||
|
);
|
||||||
|
|
||||||
const handlePieceDragEnd = () => {
|
const handlePieceDragEnd = useCallback(() => {
|
||||||
resetMoveClick();
|
resetMoveClick();
|
||||||
};
|
}, [resetMoveClick]);
|
||||||
|
|
||||||
const onPromotionPieceSelect = (
|
const onPromotionPieceSelect = useCallback(
|
||||||
piece?: PromotionPieceOption,
|
(piece?: PromotionPieceOption, from?: Square, to?: Square) => {
|
||||||
from?: Square,
|
|
||||||
to?: Square
|
|
||||||
) => {
|
|
||||||
if (!piece) return false;
|
if (!piece) return false;
|
||||||
const promotionPiece = piece[1]?.toLowerCase() ?? "q";
|
const promotionPiece = piece[1]?.toLowerCase() ?? "q";
|
||||||
|
|
||||||
@@ -188,7 +204,9 @@ export default function Board({
|
|||||||
|
|
||||||
resetMoveClick(moveClickFrom);
|
resetMoveClick(moveClickFrom);
|
||||||
return false;
|
return false;
|
||||||
};
|
},
|
||||||
|
[moveClickFrom, moveClickTo, playMove, resetMoveClick]
|
||||||
|
);
|
||||||
|
|
||||||
const customArrows: Arrow[] = useMemo(() => {
|
const customArrows: Arrow[] = useMemo(() => {
|
||||||
const bestMove = position?.lastEval?.bestMove;
|
const bestMove = position?.lastEval?.bestMove;
|
||||||
@@ -249,6 +267,22 @@ export default function Board({
|
|||||||
[pieceSet]
|
[pieceSet]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const customBoardStyle = useMemo(() => {
|
||||||
|
const commonBoardStyle = {
|
||||||
|
borderRadius: "5px",
|
||||||
|
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.5)",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (boardHue) {
|
||||||
|
return {
|
||||||
|
...commonBoardStyle,
|
||||||
|
filter: `hue-rotate(${boardHue}deg)`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return commonBoardStyle;
|
||||||
|
}, [boardHue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
@@ -293,11 +327,7 @@ export default function Board({
|
|||||||
boardOrientation={
|
boardOrientation={
|
||||||
boardOrientation === Color.White ? "white" : "black"
|
boardOrientation === Color.White ? "white" : "black"
|
||||||
}
|
}
|
||||||
customBoardStyle={{
|
customBoardStyle={customBoardStyle}
|
||||||
borderRadius: "5px",
|
|
||||||
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.5)",
|
|
||||||
filter: `hue-rotate(${boardHue}deg)`,
|
|
||||||
}}
|
|
||||||
customArrows={customArrows}
|
customArrows={customArrows}
|
||||||
isDraggablePiece={isPiecePlayable}
|
isDraggablePiece={isPiecePlayable}
|
||||||
customSquare={SquareRenderer}
|
customSquare={SquareRenderer}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { CurrentPosition } from "@/types/eval";
|
|||||||
import { MoveClassification } from "@/types/enums";
|
import { MoveClassification } from "@/types/enums";
|
||||||
import { PrimitiveAtom, atom, useAtomValue } from "jotai";
|
import { PrimitiveAtom, atom, useAtomValue } from "jotai";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { CSSProperties, forwardRef } from "react";
|
import { CSSProperties, forwardRef, useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
CustomSquareProps,
|
CustomSquareProps,
|
||||||
Square,
|
Square,
|
||||||
@@ -36,15 +36,21 @@ export function getSquareRenderer({
|
|||||||
const toSquare = position.lastMove?.to;
|
const toSquare = position.lastMove?.to;
|
||||||
const moveClassification = position?.eval?.moveClassification;
|
const moveClassification = position?.eval?.moveClassification;
|
||||||
|
|
||||||
const highlightSquareStyle: CSSProperties | undefined =
|
const highlightSquareStyle: CSSProperties | undefined = useMemo(
|
||||||
|
() =>
|
||||||
clickedSquares.includes(square)
|
clickedSquares.includes(square)
|
||||||
? rightClickSquareStyle
|
? rightClickSquareStyle
|
||||||
: fromSquare === square || toSquare === square
|
: fromSquare === square || toSquare === square
|
||||||
? previousMoveSquareStyle(moveClassification)
|
? previousMoveSquareStyle(moveClassification)
|
||||||
: undefined;
|
: undefined,
|
||||||
|
[clickedSquares, square, fromSquare, toSquare, moveClassification]
|
||||||
|
);
|
||||||
|
|
||||||
const playableSquareStyle: CSSProperties | undefined =
|
const playableSquareStyle: CSSProperties | undefined = useMemo(
|
||||||
playableSquares.includes(square) ? playableSquareStyles : undefined;
|
() =>
|
||||||
|
playableSquares.includes(square) ? playableSquareStyles : undefined,
|
||||||
|
[playableSquares, square]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -52,7 +58,7 @@ export function getSquareRenderer({
|
|||||||
style={{
|
style={{
|
||||||
...style,
|
...style,
|
||||||
position: "relative",
|
position: "relative",
|
||||||
filter: `hue-rotate(-${boardHue}deg)`,
|
filter: boardHue ? `hue-rotate(-${boardHue}deg)` : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
Reference in New Issue
Block a user