Skip to content

@xmachines/play-react-router

Documentation / @xmachines/play-react-router

React Router v7 adapter for XMachines Play using RouterBridgeBase.

Overview

@xmachines/play-react-router connects react-router v7 data routers to Play actors.

The package provides:

  • ReactRouterBridge for direct adapter control
  • PlayRouterProvider for React lifecycle wiring
  • RouteMap utilities for state ID <-> URL path resolution

Internally, ReactRouterBridge extends RouterBridgeBase from @xmachines/play-router, so behavior matches other bridge adapters in the monorepo.

Installation

Terminal window
npm install react react-router
npm install @xmachines/play-react-router @xmachines/play-router @xmachines/play-react

Current Exports

  • ReactRouterBridge
  • PlayRouterProvider + PlayRouterProviderProps
  • RouteMap
  • createRouteMapFromTree
  • type re-exports: RouterBridge, PlayRouteEvent

Peer dependencies:

  • react ^18 || ^19
  • react-router ^7.0.0

Use @xmachines/play-react for framework-native rendering (PlayRenderer).

Quick Start

import { createBrowserRouter } from "react-router";
import { definePlayer } from "@xmachines/play-xstate";
import { extractMachineRoutes } from "@xmachines/play-router";
import { ReactRouterBridge, createRouteMapFromTree } from "@xmachines/play-react-router";
const router = createBrowserRouter(routes);
const actor = definePlayer({ machine, catalog })();
actor.start();
const routeTree = extractMachineRoutes(machine);
const routeMap = createRouteMapFromTree(routeTree);
const bridge = new ReactRouterBridge(router, actor, routeMap);
bridge.connect();
// later
bridge.disconnect();

ReactRouterBridge requires the data-router API (createBrowserRouter). BrowserRouter is not supported because it does not expose subscribe/navigate APIs needed by the bridge.

API

ReactRouterBridge

class ReactRouterBridge extends RouterBridgeBase {
constructor(
router: ReturnType<typeof createBrowserRouter>,
actor: AbstractActor<AnyActorLogic> & Routable,
routeMap: RouteMap,
);
connect(): void;
disconnect(): void;
}

Responsibilities:

  • Watch React Router location updates and sync actor via play.route
  • Observe actor route changes and navigate router when state changes
  • Handle initial URL sync on cold load/deep links

PlayRouterProvider

React wrapper that creates/connects/disconnects ReactRouterBridge in useEffect:

interface PlayRouterProviderProps {
actor: AbstractActor<AnyActorLogic> & Routable & Viewable;
router: ReturnType<typeof createBrowserRouter>;
routeMap: RouteMap;
renderer: (
actor: AbstractActor<AnyActorLogic> & Routable & Viewable,
router: ReturnType<typeof createBrowserRouter>,
) => ReactNode;
}

RouteMap and createRouteMapFromTree

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 methods
class RouteMap extends BaseRouteMap {}
// Inherited API:
routeMap.getStateIdByPath(path: string): string | null
routeMap.getPathByStateId(stateId: string): string | null
// Factory from a machine route tree:
function createRouteMapFromTree(routeTree: RouteTree): RouteMap

getStateIdByPath returns null (not undefined) for unmatched paths.

Construct directly when you have static mappings:

import { RouteMap } from "@xmachines/play-react-router";
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"); // null

Or build from a machine’s route tree:

import { extractMachineRoutes } from "@xmachines/play-router";
import { createRouteMapFromTree } from "@xmachines/play-react-router";
const routeMap = createRouteMapFromTree(extractMachineRoutes(machine));

Examples

  • Routing patterns guide: docs/examples/routing-patterns.md
  • Multi-router integration guide: docs/examples/multi-router-integration.md

Architecture

Bridge-first adapter flow:

  1. Build route map from extractMachineRoutes(machine).
  2. Connect ReactRouterBridge (or PlayRouterProvider).
  3. Router navigation emits path updates to actor via play.route events.
  4. Actor transitions (and guards) determine valid state.
  5. Actor route signal updates router URL when accepted.

This keeps infrastructure passive and preserves Actor Authority.

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-react-router

React Router v7 adapter for XMachines Play architecture. Synchronizes browser URL with actor state using createBrowserRouter data API.

Classes

Interfaces

Functions