@xmachines/play-tanstack-router
API / @xmachines/play-tanstack-router
Shared, framework-agnostic TanStack Router bridge base for XMachines Play.
TanStack Router gives React and Solid the same navigate, load, and history
surface. Therefore the complete bridge implementation lives here, in
TanStackRouterBridgeBase. That class extends RouterBridgeBase from
@xmachines/play-router. Each framework adapter
package makes a subclass of it, and binds its own router type.
This package has no TanStack runtime dependency. TanStackRouterLike is a
type-only interface. It describes the small router surface that the bridge uses.
Installation
pnpm add @xmachines/play-tanstack-router @xmachines/corePeer dependencies. Install them with the package:
@xmachines/core— the base package. This package reads the helpers of itsutilssubpath.
Who consumes it
@xmachines/play-tanstack-react-router— TanStack Router adapter (React)@xmachines/play-tanstack-solid-router— TanStack Router adapter (SolidJS)
Usage
import { createMachine } from "xstate";import { definePlayer, compose, PlayerActor } from "@xmachines/play-xstate";import { formatPlayRouteTransitions, withRouting } from "@xmachines/play-xstate/routing";import { createRouteMap } from "@xmachines/play-router/xstate";import { TanStackRouterBridgeBase, type TanStackRouterLike } from "@xmachines/play-tanstack-router";
const machine = createMachine( formatPlayRouteTransitions({ id: "app", initial: "home", states: { home: { id: "home", meta: { route: "/" } }, about: { id: "about", meta: { route: "/about" } }, }, }),);
// The bridge needs the routing capabilityconst actor = definePlayer({ machine, actor: compose(PlayerActor, withRouting) })();actor.start();
const routeMap = createRouteMap(machine);
export class MyTanStackBridge extends TanStackRouterBridgeBase {}
// Your TanStack Router instance (from the React or Solid createRouter)declare const router: TanStackRouterLike;
const bridge = new MyTanStackBridge(router, actor, routeMap);bridge.connect();// Disconnect the bridge at teardownbridge.disconnect();Corrective navigation and a mounted <RouterProvider>
The bridge subscribes to router.history, and it calls router.load() for every
history event. The bridge waits for that load() promise before it synchronizes
the actor. The wait is necessary for a mounted <RouterProvider>: its
Transitioner component defers router.updateLatestLocation() into the
startTransition of the framework. Without the wait, router.latestLocation
still holds the previous href while the bridge runs. A corrective navigation for a
refused URL then looks like a navigation to the same URL, and commitLocation of
TanStack writes nothing to the browser history. The refused URL then stays in the
address bar. With the wait, router.latestLocation is current, and the correction
reaches the history. The bridge therefore works with a mounted <RouterProvider>
and also without one.
A burst of history events keeps its order: each event takes a sequence number, and
a deferred synchronization runs only while its number is still the newest one. A
disconnect() call retires every synchronization that still waits.
Exports
TanStackRouterBridgeBase— the concrete bridge base class. Use it directly, or make a subclass of itTanStackRouterLike— the TanStack router surface, as a type-only interfaceTanStackRouteMapLike— the narrow route-map surface that the bridge requires
License
MIT
@xmachines/play-tanstack-router
The shared, framework-agnostic TanStack Router bridge base for XMachines Play.
@xmachines/play-tanstack-react-router and
@xmachines/play-tanstack-solid-router use it. Each of them makes a subclass of
TanStackRouterBridgeBase, and the subclass binds its own router type.