Skip to content

Commit 7624819

Browse files
committed
perf: 노드 클릭 시 렌더링 최적화
1 parent f32311b commit 7624819

File tree

3 files changed

+51
-44
lines changed

3 files changed

+51
-44
lines changed

apps/frontend/src/entities/node/ui/NoteNode/index.tsx

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,25 @@
1-
import { useEffect, useState } from "react";
21
import { FileText } from "lucide-react";
32
import { Handle, NodeProps, Position } from "@xyflow/react";
43

54
import { NoteNodeType } from "../../model/nodeTypes";
6-
import { usePageStore } from "@/entities/page";
7-
import { useUserStore } from "@/entities/user";
5+
import { type User } from "@/entities/user";
86
import { ActiveUser, Emoji } from "@/shared/ui";
97

10-
export function NoteNode({ data }: NodeProps<NoteNodeType>) {
11-
const { currentPage, setCurrentPage } = usePageStore();
12-
const { users } = useUserStore();
13-
14-
const [activeUsers, setActiveUsers] = useState(users);
15-
16-
useEffect(() => {
17-
setActiveUsers(users);
18-
}, [users]);
19-
20-
const handleNodeClick = () => {
21-
const id = data.id;
22-
if (id === undefined || id === null) {
23-
return;
24-
}
25-
26-
setCurrentPage(id);
27-
};
8+
interface NoteNodeProps extends NodeProps<NoteNodeType> {
9+
isClicked: boolean;
10+
handleNodeClick: () => void;
11+
users: User[];
12+
}
2813

14+
export function NoteNode({
15+
data,
16+
isClicked,
17+
users,
18+
handleNodeClick,
19+
}: NoteNodeProps) {
2920
return (
3021
<div
31-
className={`h-24 w-48 rounded-lg border-[1px] ${currentPage === data.id ? "border-[#8dbaef]" : "border-[#eaeaea]"} bg-white p-3 shadow-sm`}
22+
className={`h-24 w-48 rounded-lg border-[1px] ${isClicked ? "border-[#8dbaef]" : "border-[#eaeaea]"} bg-white p-3 shadow-sm`}
3223
onClick={handleNodeClick}
3324
>
3425
<Handle
@@ -68,12 +59,7 @@ export function NoteNode({ data }: NodeProps<NoteNodeType>) {
6859
)}
6960
<div className="w-full truncate">{data.title}</div>
7061
</div>
71-
<ActiveUser
72-
className="self-end"
73-
users={activeUsers.filter(
74-
(user) => user.currentPageId === data.id.toString(),
75-
)}
76-
/>
62+
<ActiveUser className="self-end" users={users} />
7763
</div>
7864
</div>
7965
);

apps/frontend/src/features/canvas/model/useCanvas.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { usePageStore } from "@/entities/page";
1919
import { createSocketIOProvider } from "@/shared/api";
2020
import { useWorkspace } from "@/shared/lib";
2121
import { useYDocStore } from "@/shared/model";
22+
import { useUserStore } from "@/entities/user";
2223

2324
export interface YNode extends Node {
2425
isHolding: boolean;
@@ -29,7 +30,6 @@ export const useCanvas = () => {
2930
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
3031
const workspace = useWorkspace();
3132
const { ydoc } = useYDocStore();
32-
3333
const { cursors, handleMouseMove, handleNodeDrag, handleMouseLeave } =
3434
useCollaborativeCursors({
3535
ydoc,
@@ -39,6 +39,7 @@ export const useCanvas = () => {
3939
const holdingNodeRef = useRef<string | null>(null);
4040

4141
const { currentPage, setCurrentPage } = usePageStore();
42+
const { users } = useUserStore();
4243

4344
const { fitView } = useReactFlow();
4445

@@ -283,17 +284,25 @@ export const useCanvas = () => {
283284
[ydoc],
284285
);
285286

287+
const handleNodeClick = useCallback((id: number) => {
288+
setCurrentPage(id);
289+
}, []);
290+
286291
return {
287-
handleMouseMove,
292+
currentPage,
288293
nodes,
289294
edges,
295+
users,
296+
setCurrentPage,
297+
handleMouseMove,
290298
handleNodesChange,
291299
handleEdgesChange,
292300
handleMouseLeave,
293301
handleNodeDrag,
294302
onNodeDragStart,
295303
onNodeDragStop,
296304
onConnect,
305+
handleNodeClick,
297306
cursors,
298307
};
299308
};

apps/frontend/src/features/canvas/ui/Canvas/index.tsx

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,56 @@ import {
66
Background,
77
BackgroundVariant,
88
ConnectionMode,
9-
type Node,
9+
NodeProps,
1010
} from "@xyflow/react";
1111
import "@xyflow/react/dist/style.css";
1212

1313
import { CollaborativeCursors } from "../CollaborativeCursors";
1414
import { useCanvas } from "../../model/useCanvas";
15-
import { MemoizedGroupNode, NoteNode } from "@/entities/node";
15+
import { MemoizedGroupNode, NoteNode, NoteNodeType } from "@/entities/node";
1616
import { cn } from "@/shared/lib";
1717

18-
const proOptions = { hideAttribution: true };
19-
20-
export interface YNode extends Node {
21-
isHolding: boolean;
22-
}
23-
2418
interface CanvasProps {
2519
className?: string;
2620
}
2721

2822
export function Canvas({ className }: CanvasProps) {
2923
const {
30-
handleMouseMove,
24+
currentPage,
3125
nodes,
3226
edges,
27+
users,
28+
cursors,
29+
handleNodeClick,
30+
handleMouseMove,
3331
handleNodesChange,
3432
handleEdgesChange,
3533
handleMouseLeave,
3634
handleNodeDrag,
3735
onNodeDragStart,
3836
onNodeDragStop,
3937
onConnect,
40-
cursors,
4138
} = useCanvas();
4239

43-
const nodeTypes = useMemo(
44-
() => ({ note: NoteNode, group: MemoizedGroupNode }),
45-
[],
46-
);
40+
const proOptions = { hideAttribution: true };
41+
42+
const nodeTypes = useMemo(() => {
43+
return {
44+
note: (props: NodeProps<NoteNodeType>) => {
45+
return (
46+
<NoteNode
47+
{...props}
48+
isClicked={currentPage === props.data.id}
49+
handleNodeClick={() => handleNodeClick(props.data.id)}
50+
users={users.filter(
51+
(user) => user.currentPageId === props.data.id.toString(),
52+
)}
53+
/>
54+
);
55+
},
56+
group: MemoizedGroupNode,
57+
};
58+
}, [users]);
4759

4860
return (
4961
<div className={cn("", className)} onMouseMove={handleMouseMove}>

0 commit comments

Comments
 (0)