Rocon Website

Deep Routes

So far we learned how to handle paths like /foo, /bar and /. Then, what about deep routes like /foo/cat and /foo/dog?

In order to handle deep routes, we create a route builder for each level and connect them by attaching a child builder to a parent builder.

const fooRoutes = Rocon.Path()
  .exact({
    action: () => <p>This is foo</p>
  })
  .route("cat", (route) => route.action(() => <p>I love cats</p>))
  .route("dog", (route) => route.action(() => <p>I love dogs</p>));

const toplevelRoutes = Rocon.Path()
  .exact({
    action: () => <p>I am top page</p>
  })
  .route("foo", (route) => route.attach(fooRoutes))
  .route("bar", (route) => route.action(() => <p>This is bar</p>));

In the above example we have two builders fooRoutes and toplevelRoutes, the former defining /, /cat and /dog and the latter defining /, /foo and /bar. Of notable is that fooRoutes is attached to the foo route of toplevelRoutes by calling route.attach. This means that the routes defined by fooRoutes is attached undertoplevelRoutes's foo route.

Therefore, I love cats should be displayed by accessing /foo/cat. Also, I love dogs should be displayed by accessing /foo/dog.

Note that fooRoutes need not be directly passed to useRoutes. Attached routes are automatically looked up while resolving locations.

Attaching to Route Records

Rocon has another API for attaching a route builder to another.

const fooRoutes = Rocon.Path()
  .exact({
    action: () => <p>This is foo</p>
  })
  .route("cat", (route) => route.action(() => <p>I love cats</p>))
  .route("dog", (route) => route.action(() => <p>I love dogs</p>));

const toplevelRoutes = Rocon.Path()
  .exact({
    action: () => <p>I am top page</p>
  })
  .route("foo")
  .route("bar", (route) => route.action(() => <p>This is bar</p>));

toplevelRoutes._.foo.attach(fooRoutes);

In this example, we only declare toplevelRoutes's foo route without attaching anything to it (in this case we can omit the callback function of route). After defining toplevelRoutes, we can retrieve the route recordof the foo route by accessing toplevelRoutes._.foo. It has an attach method for attaching a child to that route.

As demonstrated above, any Path route builder has an _ property which is a collection of route records of all named route in it. A route record can be used to attach a child to it. Also, it will be used for navigation later in this tutorial.

This is the first piece you have encountered of Rocon's ultimate type safety. The _ property should only have defined routes in it, namely foo and bar in this case. Accessing toplevelRoutes._.notdefined should be a type error.

Since a route record's attach method returns what is passed as an argument, it allows yet another “top-to-bottom” coding style like this:

const toplevelRoutes = Rocon.Path()
  .exact({
    action: () => <p>I am top page</p>
  })
  .route("foo")
  .route("bar", (route) => route.action(() => <p>This is bar</p>));

const fooRoutes = toplevelRoutes._.foo.attach(Rocon.Path())
  .exact({
    action: () => <p>This is foo</p>
  })
  .route("cat", (route) => route.action(() => <p>I love cats</p>))
  .route("dog", (route) => route.action(() => <p>I love dogs</p>));

The last one is most recommended for it gets maximal benefit of type inference.