Skip to content

Commit 803e801

Browse files
committed
⚡ refactor(LayerPanel): use childrenMap/nodeMap for O(1) node lookups
1 parent f6da35c commit 803e801

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

apps/editor/db.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"parent_id": null,
77
"type": "Stack",
88
"position": 0,
9+
"_comment": "position 데모: 자식들의 position 순서가 DB 순서와 다릅니다",
910
"layout": {
1011
"x": 100,
1112
"y": 100,
@@ -33,7 +34,7 @@
3334
"page_id": 201,
3435
"parent_id": "page",
3536
"type": "Stack",
36-
"position": 0,
37+
"position": 3,
3738
"layout": {
3839
"x": 0,
3940
"y": 0,
@@ -87,7 +88,7 @@
8788
"page_id": 201,
8889
"parent_id": "page",
8990
"type": "Stack",
90-
"position": 1,
91+
"position": 2,
9192
"layout": {
9293
"x": 0,
9394
"y": 0,
@@ -141,7 +142,7 @@
141142
"page_id": 201,
142143
"parent_id": "page",
143144
"type": "Stack",
144-
"position": 2,
145+
"position": 1,
145146
"layout": {
146147
"x": 0,
147148
"y": 0,
@@ -196,7 +197,7 @@
196197
"page_id": 201,
197198
"parent_id": "page",
198199
"type": "Stack",
199-
"position": 3,
200+
"position": 0,
200201
"layout": {
201202
"x": 0,
202203
"y": 0,

apps/editor/src/widgets/left-sidebar/ui/sub-panels/LayerPanel.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PanelBaseLayout } from './base/PanelBaseLayout';
2-
import { useCurNodes, useSelectNode, useSelectedNodeId, useDeleteNode, useAddNode } from '../../../../stores/useEditorStore';
2+
import { useSelectNode, useSelectedNodeId, useDeleteNode, useAddNode, useChildrenMap, useNodeMap } from '../../../../stores/useEditorStore';
33
import { COMPONENT_DEFAULTS } from '../../../../shared/lib/component-defaults';
44
import { cn } from '@repo/utils';
55
import {
@@ -37,19 +37,18 @@ const NODE_TYPE_ICONS: Record<string, LucideIcon> = {
3737

3838
interface LayerItemProps {
3939
node: WcxNode;
40-
nodes: WcxNode[];
40+
childrenMap: Record<string, WcxNode[]>;
4141
selectedId: string | null;
4242
onSelect: (id: string) => void;
4343
onContextMenu: (e: React.MouseEvent, nodeId: string) => void;
4444
depth: number;
4545
}
4646

47-
const LayerItem = ({ node, nodes, selectedId, onSelect, onContextMenu, depth }: LayerItemProps) => {
47+
const LayerItem = ({ node, childrenMap, selectedId, onSelect, onContextMenu, depth }: LayerItemProps) => {
4848
const [isExpanded, setIsExpanded] = useState(true);
4949

50-
const children = nodes
51-
.filter((n) => n.parent_id === node.id)
52-
.sort((a, b) => a.position - b.position);
50+
// childrenMap에서 O(1) 조회 (filter+sort 제거)
51+
const children = childrenMap[node.id] || [];
5352

5453
const hasChildren = children.length > 0;
5554
const isSelected = selectedId === node.id;
@@ -117,7 +116,7 @@ const LayerItem = ({ node, nodes, selectedId, onSelect, onContextMenu, depth }:
117116
<LayerItem
118117
key={child.id}
119118
node={child}
120-
nodes={nodes}
119+
childrenMap={childrenMap}
121120
selectedId={selectedId}
122121
onSelect={onSelect}
123122
onContextMenu={onContextMenu}
@@ -133,7 +132,8 @@ const LayerItem = ({ node, nodes, selectedId, onSelect, onContextMenu, depth }:
133132
/* ─────────────────────── Layer Panel ─────────────────────── */
134133

135134
export const LayerPanel = () => {
136-
const nodes = useCurNodes() || [];
135+
const nodeMap = useNodeMap();
136+
const childrenMap = useChildrenMap();
137137
const selectedId = useSelectedNodeId();
138138
const selectNode = useSelectNode();
139139
const deleteNode = useDeleteNode();
@@ -150,7 +150,8 @@ export const LayerPanel = () => {
150150
const handleContextMenu = (e: React.MouseEvent, nodeId: string) => {
151151
e.preventDefault();
152152
e.stopPropagation();
153-
const targetNode = nodes.find((n) => n.id === nodeId);
153+
// nodeMap에서 O(1) 조회
154+
const targetNode = nodeMap[nodeId];
154155
if (!targetNode) return;
155156
setContextMenu({ x: e.clientX, y: e.clientY, nodeId, nodeType: targetNode.type });
156157
};
@@ -161,8 +162,9 @@ export const LayerPanel = () => {
161162
const defaults = COMPONENT_DEFAULTS[type];
162163
if (!defaults) return;
163164

164-
const siblingCount = nodes.filter((n) => n.parent_id === parentId).length;
165-
const parentNode = nodes.find((n) => n.id === parentId);
165+
// childrenMap에서 형제 수 조회
166+
const siblingCount = (childrenMap[parentId] || []).length;
167+
const parentNode = nodeMap[parentId];
166168

167169
const newNode: WcxNode = {
168170
id: `${type.toLowerCase()}-${Date.now()}`,
@@ -181,12 +183,11 @@ export const LayerPanel = () => {
181183

182184
addNode(newNode);
183185
},
184-
[nodes, addNode],
186+
[childrenMap, nodeMap, addNode],
185187
);
186188

187-
const rootNodes = nodes
188-
.filter((node) => node.parent_id === null)
189-
.sort((a, b) => a.position - b.position);
189+
// 루트 노드: childrenMap["__root__"]에서 바로 조회 (이미 정렬됨)
190+
const rootNodes = childrenMap["__root__"] || [];
190191

191192
return (
192193
<PanelBaseLayout title="레이어" description="페이지 구성 요소 계층">
@@ -196,7 +197,7 @@ export const LayerPanel = () => {
196197
<LayerItem
197198
key={node.id}
198199
node={node}
199-
nodes={nodes}
200+
childrenMap={childrenMap}
200201
selectedId={selectedId}
201202
onSelect={selectNode}
202203
onContextMenu={handleContextMenu}

0 commit comments

Comments
 (0)