fix: boards rerender optimization

This commit is contained in:
2025-08-21 16:45:04 +04:00
parent f3df8840df
commit cb67c913ad
9 changed files with 51 additions and 83 deletions

View File

@ -11,7 +11,7 @@ import { BoardSchema } from "@/lib/client";
import styles from "./Boards.module.css"; import styles from "./Boards.module.css";
const Boards = () => { const Boards = () => {
const { boards, setSelectedBoard, onUpdateBoard } = useBoardsContext(); const { boards, setSelectedBoardId, onUpdateBoard } = useBoardsContext();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const renderBoard = (board: BoardSchema) => <Board board={board} />; const renderBoard = (board: BoardSchema) => <Board board={board} />;
@ -21,7 +21,7 @@ const Boards = () => {
}; };
const selectBoard = (board: BoardSchema) => { const selectBoard = (board: BoardSchema) => {
setSelectedBoard(board); setSelectedBoardId(board.id);
}; };
return ( return (

View File

@ -11,7 +11,7 @@ import useIsMobile from "@/hooks/useIsMobile";
const Header = () => { const Header = () => {
const { const {
projects, projects,
setSelectedProject, setSelectedProjectId,
selectedProject, selectedProject,
setIsEditorDrawerOpened: setIsProjectsDrawerOpened, setIsEditorDrawerOpened: setIsProjectsDrawerOpened,
} = useProjectsContext(); } = useProjectsContext();
@ -35,7 +35,9 @@ const Header = () => {
<ProjectSelect <ProjectSelect
data={projects} data={projects}
value={selectedProject} value={selectedProject}
onChange={value => value && setSelectedProject(value)} onChange={value =>
value && setSelectedProjectId(value.id)
}
style={{ minWidth: 200 }} style={{ minWidth: 200 }}
/> />
</Flex> </Flex>

View File

@ -1,12 +1,6 @@
"use client"; "use client";
import React, { import React, { createContext, FC, useContext, useState } from "react";
createContext,
FC,
useContext,
useEffect,
useState,
} from "react";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext"; import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import useBoardsList from "@/hooks/useBoardsList"; import useBoardsList from "@/hooks/useBoardsList";
import { useBoardsOperations } from "@/hooks/useBoardsOperations"; import { useBoardsOperations } from "@/hooks/useBoardsOperations";
@ -16,7 +10,7 @@ type BoardsContextState = {
boards: BoardSchema[]; boards: BoardSchema[];
setBoards: React.Dispatch<React.SetStateAction<BoardSchema[]>>; setBoards: React.Dispatch<React.SetStateAction<BoardSchema[]>>;
selectedBoard: BoardSchema | null; selectedBoard: BoardSchema | null;
setSelectedBoard: React.Dispatch<React.SetStateAction<BoardSchema | null>>; setSelectedBoardId: React.Dispatch<React.SetStateAction<number | null>>;
refetchBoards: () => void; refetchBoards: () => void;
onCreateBoard: (name: string) => void; onCreateBoard: (name: string) => void;
onUpdateBoard: (boardId: number, board: UpdateBoardSchema) => void; onUpdateBoard: (boardId: number, board: UpdateBoardSchema) => void;
@ -34,28 +28,17 @@ const useBoardsContextState = () => {
setBoards, setBoards,
refetch: refetchBoards, refetch: refetchBoards,
} = useBoardsList({ projectId: project?.id }); } = useBoardsList({ projectId: project?.id });
const [selectedBoard, setSelectedBoard] = useState<BoardSchema | null>(
null
);
const [isEditorDrawerOpened, setIsEditorDrawerOpened] = const [isEditorDrawerOpened, setIsEditorDrawerOpened] =
useState<boolean>(false); useState<boolean>(false);
useEffect(() => { const [selectedBoardId, setSelectedBoardId] = useState<number | null>(null);
if (boards.length > 0 && selectedBoard === null) { const selectedBoard =
setSelectedBoard(boards[0]); boards.find(board => board.id === selectedBoardId) ?? null;
return;
if (selectedBoard === null && boards.length > 0) {
setSelectedBoardId(boards[0].id);
} }
if (!selectedBoard) return;
let newBoard = boards.find(board => board.id === selectedBoard.id);
if (!newBoard && boards.length > 0) {
newBoard = boards[0];
}
setSelectedBoard(newBoard ?? null);
}, [boards]);
const { onCreateBoard, onUpdateBoard, onDeleteBoard } = useBoardsOperations( const { onCreateBoard, onUpdateBoard, onDeleteBoard } = useBoardsOperations(
{ {
boards, boards,
@ -69,7 +52,7 @@ const useBoardsContextState = () => {
boards, boards,
setBoards, setBoards,
selectedBoard, selectedBoard,
setSelectedBoard, setSelectedBoardId,
refetchBoards, refetchBoards,
onCreateBoard, onCreateBoard,
onUpdateBoard, onUpdateBoard,

View File

@ -1,21 +1,13 @@
"use client"; "use client";
import React, { import React, { createContext, FC, useContext, useState } from "react";
createContext,
FC,
useContext,
useEffect,
useState,
} from "react";
import useProjectsList from "@/hooks/useProjectsList"; import useProjectsList from "@/hooks/useProjectsList";
import { useProjectsOperations } from "@/hooks/useProjectsOperations"; import { useProjectsOperations } from "@/hooks/useProjectsOperations";
import { ProjectSchema, UpdateProjectSchema } from "@/lib/client"; import { ProjectSchema, UpdateProjectSchema } from "@/lib/client";
type ProjectsContextState = { type ProjectsContextState = {
selectedProject: ProjectSchema | null; selectedProject: ProjectSchema | null;
setSelectedProject: React.Dispatch< setSelectedProjectId: React.Dispatch<React.SetStateAction<number | null>>;
React.SetStateAction<ProjectSchema | null>
>;
projects: ProjectSchema[]; projects: ProjectSchema[];
onCreateProject: (name: string) => void; onCreateProject: (name: string) => void;
onUpdateProject: (projectId: number, project: UpdateProjectSchema) => void; onUpdateProject: (projectId: number, project: UpdateProjectSchema) => void;
@ -36,24 +28,16 @@ const useProjectsContextState = () => {
setProjects, setProjects,
refetch: refetchProjects, refetch: refetchProjects,
} = useProjectsList(); } = useProjectsList();
const [selectedProject, setSelectedProject] =
useState<ProjectSchema | null>(null);
useEffect(() => { const [selectedProjectId, setSelectedProjectId] = useState<number | null>(
if (projects.length > 0) { null
if (selectedProject) {
setSelectedProject(
projects.find(
project => project.id === selectedProject.id
) ?? null
); );
return; const selectedProject =
projects.find(project => project.id === selectedProjectId) ?? null;
if (selectedProject === null && projects.length > 0) {
setSelectedProjectId(projects[0].id);
} }
setSelectedProject(projects[0]);
return;
}
setSelectedProject(null);
}, [projects]);
const { onCreateProject, onUpdateProject, onDeleteProject } = const { onCreateProject, onUpdateProject, onDeleteProject } =
useProjectsOperations({ useProjectsOperations({
@ -65,7 +49,7 @@ const useProjectsContextState = () => {
return { return {
projects, projects,
selectedProject, selectedProject,
setSelectedProject, setSelectedProjectId,
onCreateProject, onCreateProject,
onUpdateProject, onUpdateProject,
onDeleteProject, onDeleteProject,

View File

@ -1,12 +1,6 @@
"use client"; "use client";
import React, { import React, { createContext, FC, useContext, useState } from "react";
createContext,
FC,
useContext,
useEffect,
useState,
} from "react";
import { useMutation, UseMutationResult } from "@tanstack/react-query"; import { useMutation, UseMutationResult } from "@tanstack/react-query";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import { useBoardsContext } from "@/app/deals/contexts/BoardsContext"; import { useBoardsContext } from "@/app/deals/contexts/BoardsContext";
@ -55,10 +49,6 @@ const useStatusesContextState = () => {
const [isEditorDrawerOpened, setIsEditorDrawerOpened] = const [isEditorDrawerOpened, setIsEditorDrawerOpened] =
useState<boolean>(false); useState<boolean>(false);
useEffect(() => {
refetchStatuses();
}, [selectedBoard]);
const updateStatus = useMutation({ const updateStatus = useMutation({
...updateStatusMutation(), ...updateStatusMutation(),
onError: error => { onError: error => {

View File

@ -11,7 +11,7 @@ type Props = {
}; };
const ProjectMobile: FC<Props> = ({ project }) => { const ProjectMobile: FC<Props> = ({ project }) => {
const { onUpdateProject, setSelectedProject, setIsEditorDrawerOpened } = const { onUpdateProject, setSelectedProjectId, setIsEditorDrawerOpened } =
useProjectsContext(); useProjectsContext();
const startEditing = () => { const startEditing = () => {
@ -27,7 +27,7 @@ const ProjectMobile: FC<Props> = ({ project }) => {
}; };
const onClick = () => { const onClick = () => {
setSelectedProject(project); setSelectedProjectId(project.id);
setIsEditorDrawerOpened(false); setIsEditorDrawerOpened(false);
}; };

View File

@ -61,7 +61,7 @@ const SortableDnd = <T extends BaseItem>({
); );
useEffect(() => { useEffect(() => {
setItems(sortByLexorank(initialItems)); setItems(initialItems);
}, [initialItems]); }, [initialItems]);
const sensors = useDndSensors(); const sensors = useDndSensors();

View File

@ -1,5 +1,6 @@
import React, { CSSProperties, ReactNode } from "react"; import React, { CSSProperties, ReactNode } from "react";
import { useDraggable } from "@dnd-kit/core"; import { useDraggable } from "@dnd-kit/core";
import useIsMobile from "@/hooks/useIsMobile";
type Props = { type Props = {
id: number | string; id: number | string;
@ -13,6 +14,7 @@ const DragHandle = ({ id, children, style, disabled }: Props) => {
id, id,
disabled, disabled,
}); });
const isMobile = useIsMobile();
return ( return (
<div <div
@ -24,6 +26,7 @@ const DragHandle = ({ id, children, style, disabled }: Props) => {
touchAction: "auto", touchAction: "auto",
...style, ...style,
}} }}
className={isMobile ? "" : "swiper-no-swiping"}
ref={setNodeRef}> ref={setNodeRef}>
{children} {children}
</div> </div>

View File

@ -15,7 +15,11 @@ import {
updateBoardMutation, updateBoardMutation,
} from "@/lib/client/@tanstack/react-query.gen"; } from "@/lib/client/@tanstack/react-query.gen";
import { notifications } from "@/lib/notifications"; import { notifications } from "@/lib/notifications";
import { getMaxByLexorank, getNewLexorank } from "@/utils/lexorank"; import {
getMaxByLexorank,
getNewLexorank,
sortByLexorank,
} from "@/utils/lexorank";
type UseBoardsOperationsProps = { type UseBoardsOperationsProps = {
boards: BoardSchema[]; boards: BoardSchema[];
@ -87,6 +91,7 @@ export const useBoardsOperations = ({
}); });
setBoards(boards => setBoards(boards =>
sortByLexorank(
boards.map(oldBoard => boards.map(oldBoard =>
oldBoard.id !== boardId oldBoard.id !== boardId
? oldBoard ? oldBoard
@ -98,6 +103,7 @@ export const useBoardsOperations = ({
: oldBoard.lexorank, : oldBoard.lexorank,
} }
) )
)
); );
}; };