Skip to content

Reduce App.tsx god-component state#127

Merged
nkcoder merged 2 commits into
mainfrom
enhancement/116-reduce-app-god-state
Jul 4, 2026
Merged

Reduce App.tsx god-component state#127
nkcoder merged 2 commits into
mainfrom
enhancement/116-reduce-app-god-state

Conversation

@nkcoder

@nkcoder nkcoder commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Closes #116.

What changed

App.tsx owned ~20 useState hooks spanning routing, config, dialogs, history, metadata cache, panel visibility, and connection warnings. Extracted the two biggest async-stateful clusters into cohesive hooks under hooks/ (matching the existing useTabManager / useQueryExecution / usePanelResize convention):

useDatasourceSession — the connection + metadata lifecycle the issue explicitly named:

  • Owns activeDatasourceId, savedQueries, completions, metadataByDs (exposed as a derived metadata), and connectionWarning.
  • Provides connect / disconnect / refreshMetadata.
  • App keeps the tab/results/view orchestration around connect/disconnect — the hook only owns session data, so the cross-cutting concerns stay where they belong.

useQueryHistory — the history drawer's open / entries / loading state + openHistory. Selecting an entry stays in App (it touches tab state).

Routing/dialog/panel booleans were deliberately left in App — they're synchronous and self-contained; wrapping them would add indirection without clarity gain (Simplicity First).

Acceptance criteria

  • Related state grouped / lifecycle extracted into a hook
  • Data flow easier to follow; re-render scope not widened — both hooks run inside App's fiber, so their state lives exactly where it did; no new context providers wrapping subtrees
  • No behavior change; existing suites pass

Testing

  • Pure internal refactor — child components and their props are untouched.
  • npm run test448 vitest tests pass unchanged (App.test.tsx + App.handlers.test.tsx drive connect/disconnect/history/metadata-warning through the real App with stubbed children).
  • +10 new hook unit tests (useDatasourceSession.test.ts, useQueryHistory.test.ts) covering connect data-load, cached-then-live metadata, connection-failure warning, disconnect, and the history open/error/close paths — also helps the App-branch coverage gap (chore: enforce 95% unit test coverage + 80% E2E flow coverage #51).
  • Affected e2e specs (history, connection-browse, sidebar) — 20 pass.
  • npm run build (tsc + Vite) clean; biome clean.

nkcoder added 2 commits July 3, 2026 20:34
App.tsx owned ~20 useState hooks mixing routing, config, dialogs,
history, metadata, panels, and connection warnings. Extract the two
biggest async-stateful clusters into cohesive hooks:

- useDatasourceSession: activeDatasourceId, savedQueries, completions,
  metadata cache, connectionWarning + connect/disconnect/refreshMetadata.
  App keeps tab/results/view orchestration; the hook owns session data.
- useQueryHistory: history drawer open/entries/loading + openHistory.

Pure internal refactor — no behavior change. Hooks live in App's fiber
so render scope is unchanged. Adds hook unit tests (10). Full vitest
suite (448) and affected e2e specs (20) pass unchanged.

Closes #116
connect() fires GetCachedMetadata and refreshMetadata concurrently; if
the live refresh resolved first, the later-arriving cache overwrote the
fresh metadata. Guard the cache write to only fill in when nothing has
landed yet, so the live refresh is always the last word.

Adds a regression test covering the live-before-cache ordering.
@nkcoder nkcoder merged commit ebac7c7 into main Jul 4, 2026
2 checks passed
@nkcoder nkcoder deleted the enhancement/116-reduce-app-god-state branch July 4, 2026 03:26
nkcoder added a commit that referenced this pull request Jul 4, 2026
…131)

* test: cover Find, ConnectionGeneralTab, and session-hook error paths

Fills gaps surfaced while regression-testing the #127#130 refactor:

- e2e/query-editor-find.spec.ts: in-editor Find (Cmd+F) had no e2e
  coverage after the #128 QueryEditor/FindBar split — open/focus/close,
  match count, next/prev navigation, clear-resets.
- ConnectionGeneralTab.test.tsx: the #129-extracted tab had no test
  (40% func) — field edits, port numeric coercion, password
  mask/reveal, isEdit placeholder, derived URL.
- useDatasourceSession: GetCompletions failure during connect/refresh;
  disconnect no-op when nothing is connected.
- useQueryHistory: null history result coerces to [].

* test: raise hooks branch coverage + set two-tier coverage thresholds

Adds the missing hooks-branch tests and turns the flat #51 threshold into
a two-tier gate:

- useSidebarTree.test.ts (new): the hook had no direct test — covers the
  live-load error branches (columns/sub-folder load failures), the
  toggleColumnsFolder guard + toggle, and each sub-folder loader.
- useQueryExecution: non-result-set (DDL) rows-affected path; error leaves
  a pinned tab intact; double-pin preserves the first; close a non-active tab.
- useDatasourceSession: successful refresh clears a same-ds warning; a
  refresh for one ds leaves another ds's warning intact.

hooks branch coverage 78.6% -> 82.7%; overall 89.8% -> 90.6% stmt.

vitest.config.ts: global ratchet floor (90/82/90/91) as a regression gate,
plus higher per-dir floors for pure logic (lib/ 97/90/100/99, hooks/
95/82/95/97). Verified the glob thresholds are enforced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reduce App.tsx god-component state

1 participant