Skip to content

fix(workspace): stop table tabs from re-browsing on every switch - #2961

Merged
openai0229 merged 3 commits into
mainfrom
fix/workspace-table-tab-refetch
Sep 28, 2026
Merged

openai0229 merged 3 commits into
mainfrom
fix/workspace-table-tab-refetch

Conversation

@openai0229

@openai0229 openai0229 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Related issue

N/A — no tracking issue exists for this defect. Found while manually testing the Community dev desktop: switching between two open table data tabs re-issued the browse request every time and pushed the result back to page 1.

Summary

A table data tab (ViewTable) started its first-page load from an effect whose dependency was the whole viewTableParams object. The workspace tab layer keeps every open tab mounted and rebuilds the tab bodies whenever unrelated workspace state changes: the active tab id is a dependency of workspaceTabItems (WorkspaceTabs/index.tsx:1991 before this change), the workspace store is subscribed through an object selector (WorkspaceTabs/index.tsx:787), and the tab body elements are recreated from that memo. React compares effect dependencies by reference, so the params object was new on most parent renders, and every tab switch re-issued viewTable for every open table tab and reset the visible page to the first one.

The fix keys the load on the table identity (datasource, database, schema, table) and reads the latest params from a ref, so a rebuilt params object no longer looks like a new table. workspaceTabItems also no longer depends on activeConsoleId, which getWorkspaceTabItems never read, so a tab switch no longer rebuilds every tab body.

Review of that change found two consequences, fixed in the second commit:

  • Loading is now keyed on the identity, so a cancelled or failed first page no longer recovers on its own — it used to be repaired by the accidental re-browse. ViewTable now catches the rejected browse (previously an unhandled rejection) and shows a retry affordance in the tab instead of staying blank until the tab is reopened.
  • changeTabDetails is captured by the memoized tab bodies, which are no longer rebuilt on a tab switch, so it could write back the split layout of an earlier render and revert a pane's active tab. It now lets setWorkspaceTabsState read the current layout from the store.

Affected surfaces

  • Frontend / Web
  • Backend / API / Storage
  • Database plugin / Driver
  • JCEF / Desktop packaging
  • CI / Build / Release
  • Documentation only

The changed client is shared by Web, the JCEF desktop renderer, and the Pro/Studio composition; no packaging or bridge behavior changed. Two user-facing strings were added to all five locale catalogs.

Verification

  • Commands and results (run in the PR worktree, NODE_ENV unset because the local shell exports production):
    • yarn run test:i18n → Validated es-ES and ko-KR against 19 frontend modules, 2 properties bundles, and 5 READMEs. (source hashes regenerated with --write-source-hashes for the two new keys)
    • yarn run test:view-table-target (new script, also appended to prebuild:web:community) → view table target tests passed
    • yarn run lint (eslint src/** + stylelint src/**, --max-warnings=0) → exit 0
    • yarn run build:web:community --app_version=0.0.0 → full prebuild test chain, Webpack: Compiled successfully, verify-production-bundles.cjs passed
    • git diff --check → clean; CI on this PR is green for Frontend, Backend, updater, repository checks, dependency review, license summary, and SBOM.
  • Manual verification: in the Community dev desktop (JCEF loading the hot dev server on 127.0.0.1:8889), switching between app.public.chat2db_orders and app.public.chat2db_geo_test no longer re-issues the browse request and no longer resets the page.
  • UI evidence: N/A (reporter screenshot shows the two affected tabs)
  • Residual gap: this repository has no React renderer test harness for this tree, and mounting ViewTable pulls in the full result-set stack, so the regression test pins the table-identity key contract instead of asserting request counts on a rendered tab; the no-refetch behavior and the retry affordance were confirmed manually.

Risk and compatibility

  • Public API or stored data: N/A — no API, request, or storage contract changed; the same viewTable request is sent, just not spuriously repeated.
  • Database or driver compatibility: N/A — no dialect, SQL builder, or metadata behavior touched.
  • Network, privacy, or security: N/A — strictly fewer duplicate requests; no new endpoint, header, or origin.
  • Community / Local / Pro boundary: N/A — the change lives in the shared client and adds no product-conditional code.
  • Backward compatibility: two intentional behavior changes. An open table tab no longer refreshes as a side effect of switching tabs (refresh paths kept: the result-set refresh shortcut, blocks/SearchResult/components/ResultSet/index.tsx:295, paging, the import-target refresh event, and reopening the tab). A cancelled or failed first page now shows an in-tab retry affordance where it previously recovered silently on the next tab switch.

Reviewer map

  • Start here: src/components/ViewTable/index.tsx — the load effect depends on getViewTableTargetKey(viewTableParams), params come from viewTableParamsRef, and the rejected browse is caught into the new retry state; the key contract lives in src/components/ViewTable/viewTableTarget.ts.
  • Then: src/pages/main/workspace/components/WorkspaceTabs/index.tsx — workspaceTabItems lost the unused activeConsoleId dependency, and changeTabDetails now reads the current layout from the store.
  • Also: src/i18n/*/common.ts (common.button.retry, common.text.tableDataNotLoaded) and the regenerated scripts/i18n-source-hashes.json.
  • Failure condition: a tab body reused for a different table without a key change, a future read of the active tab id inside getWorkspaceTabItems, or an in-tab paging caller driving viewTableParams.pageNo would reintroduce stale or repeated loads; the unit test pins the key contract.
  • Rollback or disable path: revert both commits. They are self-contained (no migration, no persistence change).

Contributor declaration

  • I linked the Issue that defines this change. (no issue exists for this defect; see Related issue)
  • I tested the affected behavior and reported the actual results above.
  • I did not include credentials, private data, or generated build output.
  • I disclosed substantial AI assistance below, or this PR contains no substantial AI-generated code.

AI assistance: the root-cause analysis, patch, review follow-ups, and tests were produced with an AI coding agent, then reviewed and manually verified in the Community dev desktop by the maintainer before this PR.

A table data tab loads its first page from an effect that depended on the
`viewTableParams` object. The workspace tab layer keeps every open tab mounted
and rebuilds the tab bodies whenever unrelated workspace state changes (active
tab, datasource list, tab list), so that object was new on most parent renders.
React compares effect dependencies by reference, so every tab switch re-issued
the browse request for every open table tab and pushed the visible page back to
the first one.

Load on the table identity (datasource, database, schema, table) and read the
latest params from a ref instead. `workspaceTabItems` also no longer depends on
the active tab id, which it never read, so switching tabs no longer rebuilds
every tab body.
@openai0229
openai0229 requested a review from a team as a code owner September 28, 2026 04:00
@openai0229 openai0229 moved this to In Review in Chat2DB Community Sep 28, 2026
Follow-up to the tab-switch load fix, from the review of that change:

- Loading is now keyed on the table identity, so a cancelled or failed first
  page no longer recovers on its own. Surface that state inside the tab and
  give it a retry button instead of leaving the tab blank until it is reopened.
- Add the missing rejection handler for the initial browse request, which was
  an unhandled rejection before.
- `changeTabDetails` is captured by the memoized tab bodies, which are no
  longer rebuilt on a tab switch, so let `setWorkspaceTabsState` read the
  current split layout from the store instead of writing back an older one.
- Document the effect-order invariant and the paging exception on the target
  key, and cover the database type and empty identity fields in its test.
@openai0229
openai0229 merged commit 489f781 into main Sep 28, 2026
16 of 19 checks passed
@openai0229
openai0229 deleted the fix/workspace-table-tab-refetch branch September 28, 2026 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant