API reference
raf-effect-atom/tanstack-router
Connects the loader verbs to TanStack Router and TanStack Start.
getRouter runs once per request on the server and once in the browser.
It makes the registry with makeRegistry, puts Loader.make(registry) on
the router context for the loaders, and calls setupRouterAtoms, which
provides the registry to the app and sends it from the server to the
browser through the router's own dehydration.
Example
import { createRouter } from "@tanstack/react-router"
import { Loader } from "raf-effect-atom"
import { makeRegistry, setupRouterAtoms } from "raf-effect-atom/tanstack-router"
export function getRouter() {
const registry = makeRegistry()
const router = createRouter({
routeTree,
context: { atoms: Loader.make(registry) }
})
setupRouterAtoms({ router, registry })
return router
}import { makeRegistry, setupRouterAtoms } from "raf-effect-atom/tanstack-router";DehydratedRouterAtoms
interface DehydratedRouterAtoms {
readonly "raf-effect-atom": ReadonlyArray<EffectHydration.DehydratedAtom>;
}The key setupRouterAtoms adds to the router's dehydrated state.
RouterAtomsOptions
interface RouterAtomsOptions<TRouter extends AnyRouter> {
/** The registry the router context's loader verbs run on. */
readonly registry: AtomRegistry.AtomRegistry;
readonly router: TRouter;
}Options for setupRouterAtoms.
makeRegistry
const makeRegistry: (options?: {
readonly defaultIdleTTL?: number | undefined;
readonly initialValues?: RequestRegistry.InitialValues | undefined;
readonly seed?: RequestRegistry.Seed | undefined;
}) => AtomRegistry.AtomRegistry;Creates the registry for one getRouter call: a request registry on the
server, and in the browser a registry like @effect/atom-react's
RegistryProvider makes.
Details
- The server is anywhere without a
window. To decide otherwise, make the registry withRequestRegistry.makeon the server andAtomRegistry.makein the browser. defaultIdleTTLis how many milliseconds the browser's registry keeps an atom no component reads, 400 by default, as@effect/atom-react's default registry does. An atom's ownAtom.setIdleTTLorAtom.keepAlivewins. The server's request registry lives for one request, so it has none.initialValuesare values both registries start with, asAtomRegistry.make'sinitialValues, such as the session the server verified or a readable atom that provides the request'sfetch. The server's request registry keeps those atoms mounted until it's disposed. The browser's registry drops an atom no component reads, value included, so make one whose value must outlive its readersAtom.keepAlive.seedruns on the server's request registry before the loaders start atoms in it, asRequestRegistry.make's does: set what the request's atoms need, such as its cookie. It can be async. The browser's registry isn't seeded.
Example
import { getRequestHeader } from "@tanstack/react-start/server"
import { makeRegistry } from "raf-effect-atom/tanstack-router"
const registry = makeRegistry({
// Keeps an issue the user navigated away from for a minute.
defaultIdleTTL: 60_000,
// In-process RPC calls send the page request's cookie.
seed: (registry) => registry.set(requestCookie, getRequestHeader("cookie"))
})setupRouterAtoms
const setupRouterAtoms: <TRouter extends AnyRouter>(
options: RouterAtomsOptions<TRouter>,
) => void;Provides a registry to a TanStack router's app and streams it from the server to the browser.
Details
- Wraps the app in
RegistryContext.Providerthrough the router'sWrapoption, inside anyWrapit has already. - On the server, adds
Hydration.dehydrate(registry)to the router's dehydrated state once the loaders have run, so results still loading cross as promises on the router's stream, and disposes the registry when the response finishes. - In the browser, hydrates the registry from that state before the app renders.
Gotchas
The server's registry must be a request registry and the browser's must not, so it throws otherwise: a registry shared between requests would send one user's results to another. Only atoms in the registry when the loaders finish are sent; one first read while rendering runs again in the browser.