Skip to content

Interface: RouteObject

API / @xmachines/play-router / index / RouteObject

Defined in: packages/play-router/src/types.ts:33

A route object, with more metadata.

Indexable

[key: string]: unknown

The additional metadata of the route: a title, a breadcrumb, and so on.

CAUTION: path, handler, reenter and data are RESERVED. The routing layer reads those four names. An unknown handler value throws an InvalidRouteHandlerError from formatPlayRouteTransitions, so the machine builds never. A data value goes to context.data, where the /context projection of every view reads it. A reenter value is the FLAG of the generated transition, and the literal true alone turns the reentry on. Give a field of your own another name.

Properties

PropertyTypeDescriptionDefined in
data?| RouteData | RouteDataResolverThe extra data that the state threads into its play.route event. The shape follows WithDynamicParams of XState, which is how XState itself parameterizes an action and a guard: the field holds a literal value, OR a function of { context, event } that returns one. // The literal form. It survives a serialization of the machine. meta: { route: { path: "/doc/:docId", data: { titleKey: "doc.view" } } } // The function form, for a value that depends on the route. meta: { route: { path: "/doc/:docId", data: ({ event }) => ({ title: Document ${event.params?.docId} }), }, } The generated transition resolves the value and assigns it to the data field of the context, beside params and query. The data of a state does NOT merge with the data of its ancestors: each state declares the whole value that its own route carries. This field and PlayRouteEvent.data are two different things, and they meet in the resolver. This field is what the STATE declares, in its machine. PlayRouteEvent.data is what the SENDER of the event supplies, such as a router bridge or the code of an application. A resolver reads event.data and returns whatever mix of the two the state needs. CAUTION: the function form holds a function inside meta, and a function does not survive JSON.stringify. A machine that Stately Studio reads, or that a process sends over a wire, must use the literal form.packages/play-router/src/types.ts:134
handler?"root" | "local" | "both"Where the generated play.route transition sits. "root" is the default, and it is what XState does: formatRouteTransitions installs every route transition on the ROOT of the machine, and each one targets its state by the ID. A route from any state therefore reaches this state. The cost is that the root is the domain of the transition, so XState re-enters each ancestor on the path to the target, and those ancestors run their entry actions again although they stay active. "local" installs the transition on the PARENT of this state instead, and it targets this state relatively. XState offers the transitions of the deepest active state node first, so the parent answers the event itself. The parent then runs its exit and its entry actions again only where the state declares reenter: true. "both" installs one transition in each place. The local one answers while the parent is active, and the root one answers a route that arrives from outside the parent. Use "both" where an ancestor holds an entry action that must run one time for each real entry, such as an analytics event or an audit record. CAUTION: "local" makes this state reachable by a route ONLY while its parent is active. A play.route event that arrives from anywhere else matches no transition and the actor does not move. A browser URL for this state therefore leaves the URL and the actor divergent. Choose "local" to SCOPE a route on purpose, for example a step that a person reaches only inside its wizard. Choose "both" where the state must stay reachable from everywhere. The field has no effect on a state whose parent IS the root: the root transition of such a state is already local to its parent, so all three values agree.packages/play-router/src/types.ts:98
pathstringThe template of the route path, for example "/user/:id".packages/play-router/src/types.ts:35
reenter?booleanThe reenter flag of the generated play.route transition. The default is false, which is also the default of XState. The flag spares the DOMAIN of the transition, and not every ancestor that stays active. Under the default placement handler: "root" the domain is the root of the machine, so false spares the root alone: each ancestor BETWEEN the root and the target still runs its exit and its entry actions, because XState re-enters every descendant of the domain that lies on the path to the target. A move between two siblings therefore still runs the entry action of their shared parent. RouteObject.handler is the field that spares those intermediate ancestors: "local" and "both" move the domain down to the parent of the state, while the parent is active. Use the two fields together where an entry action must run one time for each state that the actor really enters. The target itself re-enters under both settings, so a route to the state that the actor already holds runs the exit and entry actions of that state again. The ROOT of the machine is the one exception: a route to the root has the root as its domain, so the flag decides. Set the field to true where the domain must run its entry actions again on each route to this state. The flag of a state applies to the routes to that state alone, and not to the routes to its descendants. The flag does not decide the destination. The value of the machine after a route is identical under both settings. A route to a state that has children still enters the initial child of that state, because XState enters the initial child of a compound target under both settings. See Play RFCpackages/play-router/src/types.ts:67