refactor(web): data through TanStack Query, no useEffect outside SSE subscriptions (CL-8438) - #883
Merged
Merged
Conversation
…etching from effects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sweeps
apps/web/srcforuseEffect, converting every remaining one thatcan be converted safely. 45 effects down to 19.
What changed
through
useQueryon sharedtenantKeys; writes invalidate instead of areloadKeycounter. The dead, uncacheduseTenancyAccesshook is deleted(
settings-access.tsalready replaced it).redirectTargetForinroutes.tsxowns every old prefix (/mission-control,/inbox,/routines,/files,/library,/settings/agents,/settings/skills); the newrouter-store.tscanonicalizes the pathbefore any screen mounts. The six route entries that existed only to
bounce, and
pages/legacy-settings-redirects.tsx, are gone.Rootreads the path withuseSyncExternalStore; thepopstatelistener lives in the store, not inan effect.
Redirectcomponent schedules thenavigate on a microtask, once per target — nothing is updated mid-render
and no frame of the route being left is painted. Used by the login
bounce,
/→ newest chat, and the settings section correction.useSyncExternalStoreover the media queries;canvas scope/route resets and the artifact save state adjusted during
render; scroll reset is a keyed ref callback (
use-scroll-reset.tsdeleted); stage search focus moves to ref callbacks and handlers.
useQueryand decideswith
useMutation; connect-service reads withuseQueryand its livefold writes into that cache (the allowed subscription exception).
through
useQuery; library selection reconciliation and bench selectionpersistence happen during render.
dither-background) and the artifact editor'sdebounce cleanup are ref callbacks with cleanups, not effects.
bunx tsc -p apps/web --noEmit,bun run fmt,bun run lintclean;bun test ./srcinapps/webis 586 pass / 0 fail. No tests were deleted —none broke.
Leftovers, with reasons
SSE subscriptions are the sanctioned exception and were left as-is
(
shell/sidebar-sections.ts,pages/chat-thread-page.tsx,pages/workbench-room-page.tsx,chat/blocks/connect-service-block-container.tsx).The rest:
main.tsx— the session probe and first-login provisioning. Both runabove the
QueryClientProvider, which lives insideShell. Hoisting theclient to
Rootwould change its "one client per signed-in shell mount"lifetime (the cache is dropped on sign-out today), and provisioning
navigates on resolution. Worth doing, but not as a side effect of this
sweep.
pages/onboarding-page.tsx(3) — a multi-phase provisioning statemachine whose effects carry their own StrictMode guard against deploying
Myra twice. Converting it is a rewrite of the boot path, not a mechanical
swap.
chat/loading-state.tsx(2 —mount delay and tip rotation),
chat/turn-activity.tsx(2 — stale-clearand the 1s elapsed tick),
pages/insights-page.tsx(the same 1s tick).refetchIntervalhas nothing to attach to; the CSS-animation equivalentswould be a design change to the loading treatment.
command-palette/use-entity-search.ts— the debounce timer. The fetch itguarded is now a
useQuery; the timer itself has no Query equivalent.useSyncExternalStoredoes not fit:shell/context-menu/lib/use-document-context-menu-trigger.ts,command-palette-provider.tsx(the workbench-not-found event) andpages/library-page.tsx(the off-route Upload event, which also clicks afile input).