@xmachines/play-tanstack-router
v3.0.0
Published
Shared TanStack Router bridge base for XMachines Play - framework-agnostic logic consumed by the TanStack React/Solid router adapters
Downloads
1,142
Maintainers
Readme
@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.
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, formatPlayRouteTransitions } from "@xmachines/play-xstate";
import { createRouteMap } from "@xmachines/play-router";
import { TanStackRouterBridgeBase } 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" } },
},
}),
);
const actor = definePlayer({ machine })();
actor.start();
const routeMap = createRouteMap(machine);
export class MyTanStackBridge extends TanStackRouterBridgeBase {}
// router: your TanStack Router instance (from the React or Solid createRouter)
const bridge = new MyTanStackBridge(router, actor, routeMap);
bridge.connect();
// Disconnect the bridge at teardown
bridge.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
