Skip to content

Commit a9898a2

Browse files
Copilothotlong
andcommitted
fix: resolve infinite render loop in recent items tracking (blank page)
The useEffect for tracking recent items had unstable array references (cleanParts, allObjects) in its dependency array that changed on every render, causing React error #185 (maximum update depth exceeded). Fix: compute derived values inside the effect body, depend only on location.pathname and the stable addRecentItem callback. Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent d690500 commit a9898a2

1 file changed

Lines changed: 21 additions & 11 deletions

File tree

apps/console/src/App.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,21 @@ export function AppContent() {
122122
const currentObjectDef = allObjects.find((o: any) => o.name === objectNameFromPath);
123123

124124
// Track recent items on route change
125+
// Only depend on location.pathname — the sole external trigger.
126+
// All other values (activeApp, allObjects, cleanParts) are derived from
127+
// stable module-level config and the current pathname, so they don't need
128+
// to be in the dependency array (and including array refs would loop).
125129
useEffect(() => {
126130
if (!activeApp) return;
131+
const parts = location.pathname.split('/').filter(Boolean);
132+
let objName = parts[2];
133+
if (objName === 'view' || objName === 'record' || objName === 'page' || objName === 'dashboard') {
134+
objName = '';
135+
}
127136
const basePath = `/apps/${activeApp.name}`;
128-
if (objectNameFromPath) {
129-
const obj = allObjects.find((o: any) => o.name === objectNameFromPath);
137+
const objects = appConfig.objects || [];
138+
if (objName) {
139+
const obj = objects.find((o: any) => o.name === objName);
130140
if (obj) {
131141
addRecentItem({
132142
id: `object:${obj.name}`,
@@ -135,22 +145,22 @@ export function AppContent() {
135145
type: 'object',
136146
});
137147
}
138-
} else if (cleanParts[2] === 'dashboard' && cleanParts[3]) {
148+
} else if (parts[2] === 'dashboard' && parts[3]) {
139149
addRecentItem({
140-
id: `dashboard:${cleanParts[3]}`,
141-
label: cleanParts[3].replace(/[-_]/g, ' ').replace(/\b\w/g, (c: string) => c.toUpperCase()),
142-
href: `${basePath}/dashboard/${cleanParts[3]}`,
150+
id: `dashboard:${parts[3]}`,
151+
label: parts[3].replace(/[-_]/g, ' ').replace(/\b\w/g, (c: string) => c.toUpperCase()),
152+
href: `${basePath}/dashboard/${parts[3]}`,
143153
type: 'dashboard',
144154
});
145-
} else if (cleanParts[2] === 'report' && cleanParts[3]) {
155+
} else if (parts[2] === 'report' && parts[3]) {
146156
addRecentItem({
147-
id: `report:${cleanParts[3]}`,
148-
label: cleanParts[3].replace(/[-_]/g, ' ').replace(/\b\w/g, (c: string) => c.toUpperCase()),
149-
href: `${basePath}/report/${cleanParts[3]}`,
157+
id: `report:${parts[3]}`,
158+
label: parts[3].replace(/[-_]/g, ' ').replace(/\b\w/g, (c: string) => c.toUpperCase()),
159+
href: `${basePath}/report/${parts[3]}`,
150160
type: 'report',
151161
});
152162
}
153-
}, [location.pathname, activeApp, allObjects, objectNameFromPath, cleanParts, addRecentItem]);
163+
}, [location.pathname, addRecentItem]); // eslint-disable-line react-hooks/exhaustive-deps
154164

155165
const handleEdit = (record: any) => {
156166
setEditingRecord(record);

0 commit comments

Comments
 (0)