Routes

Tidying Up Urls

The Navigation router sees Urls as clothes draped over the body of your data, while other routers tattoo them into the skin. You can change clothes without impacting the body, but tattoos you can't. The Navigation router ships with a wrinkled wardrobe to get you started. You can iron out the creases once your appliction's running smoothly.

Let's take the example of an email application. The scruffy Url the Navigation router generates for opening an email with an id of '12' is '/mail?id=121_2'. We'll smarten up the Url in three stages so that, by the end, it will read '/open/12'.

<NavigationReact.NavigationLink 
  stateKey="mail"
  navigationData={{id: 12}}>
  Open Mail
</NavigationReact.NavigationLink>

1. Configuring Routes

Because we've not supplied a route for the 'mail' State, the Navigation router uses the State's key instead. We'll change the Url from '/mail?id=121_2' to '/open?id=121_2' by setting the State's route property.

const stateNavigator = new StateNavigator([
  {key: 'inbox', route: ''},
  {key: 'mail', route: 'open'},
  {key: 'compose'}
]);

2. Configuring Types

You'll recall that the Navigation router passes around typed data. By default it uses the Url to keep track of this type information. In the example Url the last three characters track that the id is a number. We'll remove these trailing characters, so that the Url reads '/open?id=12' instead of '/open?id=121_2', by assigning the id a type of 'number'. The other supported types are 'boolean' and 'date' ('string' is the default).

const stateNavigator = new StateNavigator([
  {key: 'inbox', route: ''},
  {key: 'mail', route: 'open', defaultTypes: {id: 'number'}},
  {key: 'compose'}
]);

3. Configuring Route Parameters

By default the Navigation router passes data in the query string. We'll iron out the final crease in the Url, changing it from '/open?id=12' to '/open/12', by specifying the id as a route parameter.

const stateNavigator = new StateNavigator([
  {key: 'inbox', route: ''},
  {key: 'mail', route: 'open/{id}', defaultTypes: {id: 'number'}},
  {key: 'compose'}
]);

Handling Optional Data

We'll pass a boolean to the 'mail' scene that indicates whether to expand the mail thread's history. This expand data item is optional so we'll assign it a default value to avoid falsy checks. The Url that opens and expands an email with an id of 12 looks like 'open/12?expand=true'. We don't have to set expand's type to 'boolean' because it's automatically deduced from the default value.

const stateNavigator = new StateNavigator([
  {key: 'inbox', route: ''},
  {key: 'mail', route: 'open/{id}', defaultTypes: {id: 'number'}, defaults: {expand: false}},
  {key: 'compose'}
]);

We want expand to be a route parameter so that the Url looks like 'open/12/true'. But setting the route to 'open/{id}/{expand}' would make expand mandatory and stop the original Url of '/open/12' from working. Instead we can set the route to 'open/{id}/{expand?}'. The '?' suffix marks the parameter as optional.

The following table summarises the different route patterns you can use for optional route parameters. Which one you choose depends on how you want the Url to look.

The example Url The State's route
'/open/12/true' 'open/{id}/{expand?}'
'/open/12/history/true' 'open/{id}+/history/{expand}'
'/true/history/12' ['open/{id}', '{expand}/history/{id}']

Handling Array Data

If we want to allow individual mails in the thread to be expanded and collapsed, we can pass expand as an array of ids rather than a boolean. We keep the Url tidy by setting expand's type to 'numberarray'. The other supported array types are 'stringarray', 'booleanarray' and 'datearray'.

const stateNavigator = new StateNavigator([
  {key: 'inbox', route: ''},
  {key: 'mail', route: 'open/{id}', defaultTypes: {expand: 'numberarray'}},
  {key: 'compose'}
]);

The Navigation router generates a Url with the array values held in separate query string parameters, each with the key 'expand'. If we expand the first and third mails in the thread the Url generated is 'open/12?expand=1&expand=3'. We can store the array as route parameters instead by configuring expand as a splat parameter using the '*' prefix. A route of 'open/{id}/{*expand?}' generates a Url of 'open/12/1/3'.

Note

Once you've configured all the types for a State, if any string value can contain underscores then you must set trackTypes to false for that State to prevent the Navigation router escaping them, e.g., {key: 'inbox', route: '', trackTypes: false}