From 39e13d31816b2e4a4cd0550a0878b0b73f56f7da Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 5 Oct 2026 12:04:52 +0800 Subject: [PATCH] Fix dependency array in RouteValidationWrapper causing loop (#51170) ## Context For staging and local only, if you opened the a table in the table editor, then navigate out, and back into the table editor - the browser freezes - The TableEditor itself has a `useEffect` that reads that and redirects to the last visited table when landing on `/editor` - `router` is in the dependency array which for the TanStack build is not a stable singleton, resulting in a redirect loop - so the main fix was to remove `router` from the dependency array - (Unrelated) Also cleaned up some logic in the redirect regarding reading the tab ID ## Summary by CodeRabbit * **Bug Fixes** * Improved table editor redirects so they select the matching open table tab from history or fall back to the first open table tab when available. --- .../pages/project/[ref]/editor/index.tsx | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/apps/studio/pages/project/[ref]/editor/index.tsx b/apps/studio/pages/project/[ref]/editor/index.tsx index 73c3c1993cc..efdaf059132 100644 --- a/apps/studio/pages/project/[ref]/editor/index.tsx +++ b/apps/studio/pages/project/[ref]/editor/index.tsx @@ -30,13 +30,21 @@ const TableEditorPage: NextPageWithLayout = () => { useEffect(() => { if (isHistoryLoaded && projectRef && router) { const lastOpenedTableId = Number(history.editor) - const lastTabId = Number( - tabStore.openTabs.find((id) => editorEntityTypes.table.includes(tabStore.tabsMap[id]?.type)) + const lastTableTabId = tabStore.openTabs.find((id) => + editorEntityTypes.table.includes(tabStore.tabsMap[id]?.type) ) + const lastTableTab = lastTableTabId ? tabStore.tabsMap[lastTableTabId] : undefined + const lastTabId = lastTableTab?.metadata?.tableId // Handle redirect to last opened table tab, or last table tab if (Number.isInteger(lastOpenedTableId)) { - const lastOpenedTableData = tabStore.tabsMap[lastOpenedTableId] + // Tabs are keyed by a prefixed id (e.g. "r-293522"), but history only stores + // the bare table id, so look up the tab by its metadata instead of by key. + const lastOpenedTableData = Object.values(tabStore.tabsMap).find( + (tab) => + editorEntityTypes.table.includes(tab.type) && + tab.metadata?.tableId === lastOpenedTableId + ) router.push( buildTableEditorUrl({ projectRef, @@ -44,19 +52,22 @@ const TableEditorPage: NextPageWithLayout = () => { schema: lastOpenedTableData?.metadata?.schema, }) ) - } else if (Number.isInteger(lastTabId)) { - const lastOpenedTableData = tabStore.tabsMap[lastTabId] + } else if (lastTabId !== undefined) { router.push( buildTableEditorUrl({ projectRef, tableId: lastTabId, - schema: lastOpenedTableData?.metadata?.schema, + schema: lastTableTab?.metadata?.schema, }) ) } } + // router is intentionally excluded: in the TanStack build useRouter() returns a + // new object on every navigation-related render, and including it here caused + // this effect to re-fire mid-navigation and push the same redirect repeatedly, + // freezing the page. // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isHistoryLoaded, projectRef, router]) + }, [isHistoryLoaded, projectRef]) return ( <>