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]: unknownThe 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
| Property | Type | Description | Defined in |
|---|---|---|---|
data? | | RouteData | RouteDataResolver | The 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 |
path | string | The template of the route path, for example "/user/:id". | packages/play-router/src/types.ts:35 |
reenter? | boolean | The 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 RFC | packages/play-router/src/types.ts:64 |