@xmachines/play-tanstack-react-router
Documentation / @xmachines/play-tanstack-react-router
TanStack React Router adapter for XMachines Play using the RouterBridge pattern.
Overview
@xmachines/play-tanstack-react-router connects a Play actor to TanStack Router through TanStackReactRouterBridge.
The bridge extends RouterBridgeBase from @xmachines/play-router, so adapter behavior stays consistent across frameworks:
- Actor route signal (
actor.currentRoute) drives router navigation. - Router history events send
play.routeintents back to the actor. - Guarded state transitions remain actor-owned (Actor Authority).
Installation
npm install @tanstack/react-router reactnpm install @xmachines/play-tanstack-react-router @xmachines/play-router @xmachines/play-reactCurrent Exports
TanStackReactRouterBridgeRouteMap,createRouteMapFromTree,RouteMapping(type)extractParams,extractQueryParamsPlayRouterProvider+PlayRouterProviderProps- re-exports:
extractMachineRoutes,createRouteMap,RouterBridge,PlayRouteEvent
Peer dependencies:
@tanstack/react-router^1.166.7react^18 || ^19xstate^5.0.0
URLPattern Support
This package uses the URLPattern API for route pattern matching via @xmachines/play-router.
URLPattern is available natively on Node.js 24+ and modern browsers (Chrome 95+, Firefox 117+, Safari 16.4+). On older environments, load a polyfill before importing this package — see @xmachines/play-router installation for details.
Quick Start
import { createRouter } from "@tanstack/react-router";import { definePlayer } from "@xmachines/play-xstate";import { extractMachineRoutes } from "@xmachines/play-router";import { TanStackReactRouterBridge, createRouteMapFromTree,} from "@xmachines/play-tanstack-react-router";
const routeTree = extractMachineRoutes(machine);const routeMap = createRouteMapFromTree(routeTree);
const router = createRouter({ routeTree: tanstackRouteTree });
const actor = definePlayer({ machine, catalog })();actor.start();
const bridge = new TanStackReactRouterBridge(router, actor, routeMap);bridge.connect();
// laterbridge.disconnect();React convenience wrapper
Use PlayRouterProvider when you want bridge lifecycle wiring in a component:
import { PlayRenderer } from "@xmachines/play-react";
<PlayRouterProvider actor={actor} router={router} routeMap={routeMap} renderer={(currentActor, currentRouter) => ( <PlayRenderer actor={currentActor} components={components} /> )}/>;API
TanStackReactRouterBridge
Primary adapter class.
class TanStackReactRouterBridge implements RouterBridge { constructor( router: TanStackRouterLike, actor: AbstractActor<AnyActorLogic> & Routable, routeMap: RouteMap, ); connect(): void; disconnect(): void;}RouteMap and createRouteMapFromTree
Map state IDs to URL paths and resolve URLs back to state IDs.
RouteMap extends BaseRouteMap from @xmachines/play-router, inheriting bucket-indexed
bidirectional route matching. No routing logic lives in the adapter itself.
// RouteMap is a thin subclass of BaseRouteMap — no extra methodsclass RouteMap extends BaseRouteMap {}
// Inherited API:routeMap.getStateIdByPath(path: string): string | nullrouteMap.getPathByStateId(stateId: string): string | null
// Factory from a machine route tree:function createRouteMapFromTree(routeTree: RouteTree): RouteMapgetStateIdByPath returns null (not undefined) for unmatched paths.
const routeMap = new RouteMap([ { stateId: "home", path: "/" }, { stateId: "profile", path: "/profile/:userId" }, { stateId: "settings", path: "/settings/:section?" },]);
routeMap.getStateIdByPath("/profile/123"); // "profile"routeMap.getPathByStateId("home"); // "/"routeMap.getStateIdByPath("/unknown"); // nullPlayRouterProvider
React wrapper around TanStackReactRouterBridge.
interface PlayRouterProviderProps { actor: AbstractActor<AnyActorLogic> & Routable & Viewable; router: TanStackRouterLike; routeMap: RouteMap; renderer: ( actor: AbstractActor<AnyActorLogic> & Routable & Viewable, router: TanStackRouterLike, ) => ReactNode;}Utilities and re-exports
extractParams,extractQueryParamsextractMachineRoutes,createRouteMap(re-exported from@xmachines/play-router)RouterBridge,PlayRouteEventtypes
Examples
- Multi-router integration guide:
docs/examples/multi-router-integration.md - Routing patterns guide:
docs/examples/routing-patterns.md
Architecture
Bridge-first flow:
RouterBridgeBase.connect()performs initial actor/router synchronization.- Actor route updates call TanStack navigation (
router.navigate({ to })). - TanStack history updates are subscribed and translated to
play.routeevents. - Actor guards accept or reject transitions; infrastructure reflects resulting state.
This keeps routing infrastructure passive while preserving business-logic control.
Historical Note
SignalSyncedHistory and createPlayRouter are legacy migration-era APIs and are not part of the current quick-start path. Use TanStackReactRouterBridge + RouteMap for new integrations.
Related Packages
License
Copyright (c) 2016 Mikael Karon. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see https://opensource.org/licenses/MIT.
@xmachines/play-tanstack-react-router
TanStack Router adapter for XMachines Play architecture. Synchronizes browser URL with actor state through passive infrastructure.