Add default 404 page and loading state to project example#1257
Add default 404 page and loading state to project example#1257KyleAMathews merged 4 commits intomainfrom
Conversation
Add a guard in the ProjectPage component to handle the case where the project or user membership data hasn't loaded yet, preventing the "Cannot read properties of undefined (reading 'name')" crash. Also add a defaultNotFoundComponent to the router to handle invalid routes gracefully instead of throwing an unconfigured notFoundError. Fixes #889 https://claude.ai/code/session_01QJP1o2CKx7s9iLPNEkwcuP
|
More templates
@tanstack/angular-db
@tanstack/db
@tanstack/db-ivm
@tanstack/electric-db-collection
@tanstack/offline-transactions
@tanstack/powersync-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
|
Size Change: 0 B Total Size: 92.1 kB ℹ️ View Unchanged
|
|
Size Change: 0 B Total Size: 3.7 kB ℹ️ View Unchanged
|
…omponent Throw notFound() from the route loader when the project ID is invalid or doesn't exist, instead of showing a misleading "Loading..." message. Extract NotFound into a reusable component using Link for client-side navigation, consistent with the todo and offline-transactions examples. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
After the _authenticated layout creates a default project with a random ID, the index route redirects to /project/. If the project data wasn't yet synced, projects[0] was undefined and the component crashed on project.name.
Since now we detect this and show a not found component, this means that we will see this NotFound page on initial login (since i would reliably get the error, so i will now reliably get this not found page). Will it automatically redirect to the project when it syncs in? Or shouldn't we wait with the redirect to the project until we are sure it synced?
EDIT: Claude's take:
The reviewer's point is that this trades a crash for a potentially confusing UX: on initial login, the user would now reliably see a "Page Not Found" page instead of a crash. The reviewer is asking:
- Will it auto-recover once the sync completes? (Probably not — the loader already ran and threw notFound(), so the user is stuck on the 404 page unless they navigate away.)
- Shouldn't the redirect itself be deferred until the data is confirmed to be synced, rather than redirecting eagerly and then showing a 404?
This is a legitimate architectural concern. The fix addresses the symptom (crash on undefined) but not the root cause (redirecting to a project before its data is available). A better approach might be:
- Show a loading state while waiting for sync to complete
- Only redirect to the project once it's confirmed to exist in the collection
- Or have the $projectId route show a loading/pending state instead of 404 when the project isn't found yet but sync is still in progress
- Move auth API route to catch-all (api/auth/$.ts) so Better Auth sub-paths like /api/auth/sign-up/email are handled correctly - Add baseURL and port 5174 to Better Auth trusted origins - Move default project creation from useEffect into beforeLoad so data is ready before first render, eliminating race conditions - Wait for project to persist before redirecting to get server-assigned ID - Remove unused useEffect and isLoading from authenticated layout Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes the React projects example which was broken on initial sign-up/sign-in due to multiple issues: a crash from accessing undefined project data, missing 404 handling, a broken auth API route, and a race condition in default project creation.
Root Causes
1. Auth API route didn't handle sub-paths — The route at
api/auth.tsonly matched/api/authexactly. Better Auth needs to handle sub-paths like/api/auth/sign-up/email, causing all auth requests to 404. Fixed by moving to a catch-all route atapi/auth/$.ts(matching the existing tRPC pattern).2. Default project creation via useEffect caused race conditions — The
_authenticatedlayout created a default project in auseEffect, thenindex.tsxredirected to it in anotheruseEffect. This meant components rendered before data was ready, causing crashes onproject.namewhenuseLiveQueryhadn't resolved yet.3. No
defaultNotFoundComponent— TanStack Router threw an unhandled error when encountering a not-found route with no fallback component configured.Approach
Move all data preparation into
beforeLoad— Auth check, collection preload, default project creation, and redirect all happen inbeforeLoadbefore any component renders. The insert waits fortx.isPersisted.promiseto get the server-assigned ID before redirecting, avoiding the stale-random-ID problem.Validate project existence in the loader — The
$projectIdroute loader checksprojectCollection.has(projectId)after preload and throwsnotFound()for invalid/missing projects.Add reusable NotFound component — Extracted to
src/components/NotFound.tsxusing<Link>for client-side navigation, consistent with the todo and offline-transactions examples.Key Invariants
preload()resolves,collection.has(key)andcollection.toArrayreflect both synced and optimistic statebeforeLoadruns sequentially (parent → child) before any component renders — no timing racesawait tx.isPersisted.promiseensures the server-assigned ID is used for redirect, not the temporary random IDNon-goals
useLiveQuerycalls — the loader validation makes this unnecessaryFiles changed
src/routes/api/auth.ts→src/routes/api/auth/$.tssrc/lib/auth.tsbaseURLconfig and port 5174 to trusted originssrc/routes/_authenticated.tsxuseEffectdefault project creationsrc/routes/_authenticated/index.tsxbeforeLoadsrc/routes/_authenticated/project/$projectId.tsxnotFound()src/components/NotFound.tsxsrc/router.tsxdefaultNotFoundComponentRelease Impact
Example-only change — no impact on published packages.
Fixes #889