Migrate Transportation view to TanStack DB#7583
Draft
hawkrives wants to merge 20 commits into
Draft
Conversation
Installs @tanstack/query-db-collection and implements busLinesCollection using queryCollectionOptions (TanStack Query sync) wrapped in persistedCollectionOptions (SQLite persistence) when available, with graceful fallback when SQLite init has failed. https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
…ions
Restores AbortSignal passthrough from QueryFunctionContext so TanStack
Query can cancel in-flight requests, and replaces the unsafe `as` cast
with typed `.json<{data: T[]}>()` plus a `select` option to extract the
items array from the wrapped API response.
https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
Replaces the TanStack React Query useQuery(busRoutesOptions) + Array.find
pattern with a direct busLinesCollection subscription via useSyncExternalStore,
using the collection's toArray getter and utils.{isLoading,isError,lastError,refetch}.
https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
Subscribe to both subscribeChanges (for data) and status:change (for loading/error transitions) so the component re-renders when fetch status changes. Use useRef to cache stable array and utils snapshots, fixing the infinite re-render loop caused by toArray returning a new reference on every call. https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
…tion views status:change only fires on collection lifecycle transitions (idle→loading→ready). Background refetch errors leave the collection in 'ready' state, so isError/isLoading changes from QueryObserver never trigger a re-render. Fix: subscribe to queryClient.getQueryCache() in both BusView and OtherModesView so all QueryObserver-level state transitions (background refetch loading, post-initial errors) update utilsRef and trigger a re-render. Also update utilsRef inside subscribeChanges so data-arrival always syncs utils state. https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
bus/query.ts and other-modes/query.ts are fully replaced by collection.ts files. No remaining imports reference them. https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
…t JSX props - Remove unnecessary `async` keyword from queryFn in both collections (no await expression; .json() already returns a Promise — fixes require-await lint) - Use `isRefetching` instead of `isLoading` for SectionList's `refreshing` prop so the pull-to-refresh spinner shows during background refetches, not just initial load - Sort SectionList JSX props alphabetically to satisfy react/jsx-sort-props rule - Prettier formatting for tanstack-db.ts and wrapper.tsx https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
getQueryCache().subscribe() fires for every query in the app. Without filtering, BusView and OtherModesView would re-render on every unrelated network response (dining menus, calendar, directory, etc.). Filter to the collection's own query key so only transitions in the transit/bus-routes and transit/modes queries trigger a utils update. Also document the module initialization ordering requirement in tanstack-db.ts: this file must run before any collection module reads the `persistence` export. https://claude.ai/code/session_01PFCyQJtzT7odhBmaoDMMLr
hawkrives
commented
Apr 28, 2026
| refetch: (typeof busLinesCollection.utils)['refetch'] | ||
| } | ||
|
|
||
| function getUtilsSnapshot(): UtilsSnapshot { |
Member
Author
There was a problem hiding this comment.
I want to play with this locally
Comment on lines
+29
to
+34
| ? persistedCollectionOptions< | ||
| UnprocessedBusLine, | ||
| string, | ||
| never, | ||
| QueryCollectionUtils<UnprocessedBusLine, string> | ||
| >({ |
Member
Author
There was a problem hiding this comment.
I want to play with this locally and see if I can get it to infer the types
drewvolz
approved these changes
May 3, 2026
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.
Summary
Migrates the Transportation view from TanStack Query +
useState/useEffectto TanStack DB 0.6 collections backed by SQLite persistence.Goals:
@op-engineering/op-sqlite)useState/useEffectchains inBusLinereplaced by inline derivation — timer tick is an input to render, not a trigger for effect chainsApproach:
@tanstack/dbqueryCollectionOptionsuses the existingQueryClientinternally, so TanStack Query stays in the project for the fetch lifecycle (stale time, refetch interval, online/focus management)source/init/tanstack-db.tsbusLinesCollectionandotherModesCollectionreplace the existingquery.tsfilesstaleTime), pull-to-refresh viacollection.utils.refetch(), background hourly refresh only while view is mounted (refetchInterval)New packages:
@tanstack/db@0.6.5,@tanstack/react-native-db-sqlite-persistence@0.1.9,@op-engineering/op-sqlite@15.2.12API Discovery Notes
@tanstack/db0.6.5 does not export React hooks (useQuery,queryCollection). React integration usesuseSyncExternalStorewith:collection.subscribeChanges()— fires when collection data changescollection.on('status:change', ...)— fires on collection lifecycle transitions (idle→loading→ready)queryClient.getQueryCache().subscribe()— catches background refetch errors that leave the collection inreadystate (sostatus:changedoesn't fire)queryCollectionOptionsis in a separate package:@tanstack/query-db-collection.Status
All tasks complete ✅
busLinesCollectionotherModesCollectionbus/wrapper.tsxbus/line.tsx(remove useState/useEffect derivation)other-modes/list.tsxKnown follow-up
getUtilsSnapshot()creates a new object on every call, so every query cache tick triggers a re-render of the collection views even ifisLoading/isErrorvalues didn't change. Fix: field-level comparison before updatingutilsRef.current. Applies to bothbus/wrapper.tsxandother-modes/list.tsx.bus/line.tsx: midnight-advanceuseEffectcomparesnewCurrentDay(derived from samenow) againstcurrentDay(also derived from samenow) — they're always equal, so auto-advance never fires. Out of scope for this migration.Design
Full design spec:
docs/superpowers/specs/2026-04-28-transportation-tanstack-db-design.mdImplementation plan:
docs/superpowers/plans/2026-04-28-transportation-tanstack-db.mdGenerated by Claude Code