Skip to content

Interface: RouteObject

API / @xmachines/play-xstate / with-routing / 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, and a release before this one read path alone. A state that carries its own handler value now throws an InvalidRouteHandlerError from formatPlayRouteTransitions, so the machine builds never; a state that carries its own data value now writes that value to context.data, where the /context projection of every view reads it. A reenter value is read as the FLAG of the generated transition, and the literal true alone turns the reentry on: the default is false, and a release before this one generated every transition with reenter: true. Give such a field 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:131
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 and runs its exit and its entry actions NOT again. "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:95
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. Use the two fields together where an entry action must run one time for each state that the actor really enters. Set the field to true where the domain must run its entry actions again on every route to a descendant. 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 the generated transition targets the state by its id, and XState enters the initial child of an id target under both settings. See Play RFCpackages/play-router/src/types.ts:64