diff --git a/solid-v2/fullstack-tanstack/README.md b/solid-v2/fullstack-tanstack/README.md index 2690b2ae..2e7ad0c0 100644 --- a/solid-v2/fullstack-tanstack/README.md +++ b/solid-v2/fullstack-tanstack/README.md @@ -22,7 +22,7 @@ Mutations are Solid server functions through TanStack's `useMutation`. One gotch The capstone. When a mutation fires, the client transport asks the server to fold refreshed data into the **same response** (subscribing a consumer in `src/App.tsx` is the opt-in). On the server, the registered collector (`src/server-config.ts`, wired via `serverFunctions.configure`) builds a fresh TanStack router + QueryClient for the page the browser is on — with the mutation's cookie effects already folded in — runs its loaders, and ships `dehydrate(queryClient)` as the payload. -The payload **is a dehydrated QueryClient**, so the client consumer is TanStack's own `hydrate(queryClient, data)`: the entries land in the cache, every `useQuery` on those keys updates, and no `invalidateQueries` refetch happens anywhere. Watch the network tab while renaming a user: exactly one `POST /_server`, and both the detail heading and the user list in the parent layout update from that one response. +The payload **is a dehydrated QueryClient**, so the client consumer is TanStack's own `hydrate(queryClient, data)`: the entries land in the cache, every `useQuery` on those keys updates, and no `invalidateQueries` refetch happens anywhere. Watch the network tab while renaming a user: exactly one `POST /_server/data/` (scripted calls have their own address under the endpoint), and both the detail heading and the user list in the parent layout update from that one response. The seams that make this work are all public, on both sides: the server-function handler's `collectFlightData` hook hands the collector a pre-digested outcome (target URL, folded cookie headers) and takes back an opaque payload; TanStack's `dehydrate`/`hydrate` pair is its own documented serialization surface. The no-JS fallback is the same machinery minus the envelope: forms also carry the server function's URL as their `action` (`src/lib/form-action.ts`), so a plain form POST runs the mutation and answers `303 See Other` back to the page, which re-renders server-side with fresh data. diff --git a/solid-v2/fullstack/README.md b/solid-v2/fullstack/README.md index 19b6f0d4..d47f9b2d 100644 --- a/solid-v2/fullstack/README.md +++ b/solid-v2/fullstack/README.md @@ -19,7 +19,7 @@ Inside a server function, `getRequestEvent()` (from `@solidjs/web`) is the curre The payoff the whole stack builds toward. When a form submits, the router sends the action call with a single-flight marker; on the server, after the mutation runs, the registered collector (`src/server-config.ts`) reruns the target route's `preload` and folds the refreshed `query()` data into the **same response**. The router seeds its cache from that envelope — no follow-up refetch, no stale frame in between. -Watch the network tab while renaming a user: exactly one `POST /_server` — the heading _and_ the user list in the layout both update from that one response. Without single-flight that interaction is a POST followed by one GET per revalidated query. +Watch the network tab while renaming a user: exactly one `POST /_server/data/` (scripted calls have their own address under the endpoint) — the heading _and_ the user list in the layout both update from that one response. Without single-flight that interaction is a POST followed by one GET per revalidated query. Two things make a route single-flight-complete, and both are already good practice: reads go through `query()`, and the route's `preload` touches every query the page renders (that is what the server reruns — `src/routes/users/[id].tsx` calls it "the page's single-flight manifest"). The no-JS fallback is the same machinery minus the envelope: the plain form POST runs the action and answers `303 See Other` back to the page, which re-renders with fresh data — one round trip there too.