fix: preserve tab state when switching between tabs
Render all tabs simultaneously with display:none for inactive ones, instead of conditionally rendering only the active tab. This prevents React from unmounting/remounting components on tab switch, preserving query results, editor cursor, AI explanations, and other local state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,8 @@ import { EntityLookupPanel } from "@/components/lookup/EntityLookupPanel";
|
||||
|
||||
export function TabContent() {
|
||||
const { tabs, activeTabId, updateTab } = useAppStore();
|
||||
const activeTab = tabs.find((t) => t.id === activeTabId);
|
||||
|
||||
if (!activeTab) {
|
||||
if (tabs.length === 0) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
||||
Open a query tab or select a table to get started.
|
||||
@@ -18,56 +17,75 @@ export function TabContent() {
|
||||
);
|
||||
}
|
||||
|
||||
switch (activeTab.type) {
|
||||
case "query":
|
||||
return (
|
||||
<WorkspacePanel
|
||||
key={activeTab.id}
|
||||
connectionId={activeTab.connectionId}
|
||||
initialSql={activeTab.sql}
|
||||
onSqlChange={(sql) => updateTab(activeTab.id, { sql })}
|
||||
/>
|
||||
);
|
||||
case "table":
|
||||
return (
|
||||
<TableDataView
|
||||
key={activeTab.id}
|
||||
connectionId={activeTab.connectionId}
|
||||
schema={activeTab.schema!}
|
||||
table={activeTab.table!}
|
||||
/>
|
||||
);
|
||||
case "structure":
|
||||
return (
|
||||
<TableStructure
|
||||
key={activeTab.id}
|
||||
connectionId={activeTab.connectionId}
|
||||
schema={activeTab.schema!}
|
||||
table={activeTab.table!}
|
||||
/>
|
||||
);
|
||||
case "roles":
|
||||
return (
|
||||
<RoleManagerView
|
||||
key={activeTab.id}
|
||||
connectionId={activeTab.connectionId}
|
||||
/>
|
||||
);
|
||||
case "sessions":
|
||||
return (
|
||||
<SessionsView
|
||||
key={activeTab.id}
|
||||
connectionId={activeTab.connectionId}
|
||||
/>
|
||||
);
|
||||
case "lookup":
|
||||
return (
|
||||
<EntityLookupPanel
|
||||
key={activeTab.id}
|
||||
connectionId={activeTab.connectionId}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{tabs.map((tab) => {
|
||||
const isActive = tab.id === activeTabId;
|
||||
let content: React.ReactNode;
|
||||
|
||||
switch (tab.type) {
|
||||
case "query":
|
||||
content = (
|
||||
<WorkspacePanel
|
||||
connectionId={tab.connectionId}
|
||||
initialSql={tab.sql}
|
||||
onSqlChange={(sql) => updateTab(tab.id, { sql })}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "table":
|
||||
content = (
|
||||
<TableDataView
|
||||
connectionId={tab.connectionId}
|
||||
schema={tab.schema!}
|
||||
table={tab.table!}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "structure":
|
||||
content = (
|
||||
<TableStructure
|
||||
connectionId={tab.connectionId}
|
||||
schema={tab.schema!}
|
||||
table={tab.table!}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "roles":
|
||||
content = (
|
||||
<RoleManagerView
|
||||
connectionId={tab.connectionId}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "sessions":
|
||||
content = (
|
||||
<SessionsView
|
||||
connectionId={tab.connectionId}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "lookup":
|
||||
content = (
|
||||
<EntityLookupPanel
|
||||
connectionId={tab.connectionId}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
content = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={tab.id}
|
||||
className="h-full"
|
||||
style={{ display: isActive ? undefined : "none" }}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user