StencilJS Router History Step-by-Step Examples

Even if you know how StencilJS Router works or even if there are bunches of articles on the internet about it, I was thinking about having an article which explains how to add Navigation in a StencilJS application Step-by-Step.

StencilJS Router History Step-by-Step Examples

Even if you know how Stencil Router works or even if there are bunches of articles on the internet about it, I was thinking about having an article which explains how to add Navigation in a Stencil application Step-by-Step.

Nothing new is in this article, it's the same piece of information related in Stencil router official wiki, the difference is all in one post and split by steps. We'll start by navigating programmatically and finish listening router history. Let's go!

Step 1. Navigate Programmatically

Any popular frameworks in this world can't live without having the ability to navigate back and forth programmatically, it's a mandatory thing, in Stencil router you can reach that by importing RouterHistory and add it in a router component "a component that has been included in a stencil-route" as a Prop. See this example:

Once injected as a Prop, you have access to the following methods on the history object to navigate:

Step 2. Pass and/or Read data from Routes

Stencil Router provides multiple options to either pass data to routes or for routes to read that data. In this section, we'll go through each way and find the best approach for any scenario. There's no restriction by using just only one option per application, use them together, as you need as each one of them has his approach.

NOTE: This list doesn't include passing props directly to a route. Info on that can be found in the stencil-route component.

Option 1. Route Parameters (params)

This is the most common and popular way to send data to routers as well as helps to create dynamic links within our application. Let's say we have this link /user/12345 where 12345 is a user ID. In this case, we set Stencil route URL as /user/:userId. By using ":someName" we tell Stencil router to to fetch that data for us and save it inside params. This is an example:

And here's an example about how to get the user ID within the route component:

So, to get router params we just have to import MatchResults from stencil router and inject it in router component as a Prop, as we did with RouterHistory.

Option 2. Route Query Parameters

After me, this option is very useful for filtering, searching, categorising or just sending any sort of optional data. It looks like this /search?searchText='Madison' and this is an example regarding how to navigate programmatically by using RouterHistory from above:

The imported history Prop will fetch each query from the path and will add to the location.query parameter. See this example:

Option 3. Route State Data

After me this is the safest way to send some data, this option is very useful when you want to send some "maybe private" data or just some big objects which you don't want to be visible in browser URL. I use this method every-time when I don't need to have a different URL.

It's some kind of optimisation, let's say you have a list of articles fetched from database, but you need all these articles within another page "of course you could create some kind of STORE - but let's not talk about this now", so to not fetch again the articles' list, you just send them via state. See the below examples:

To get the state data, we will use the same RouterHistory from previous examples:

Step 3. Add Authentication for some Routes

Sometimes we need to allow access to some Routes just for specific users or show different content in our application depending on a certain state. This can be done by creating Functional Components to wrap our routes.

There are other methods of solving this issue, but this is probably the most straightforward.

Let's begin with creating a fake service:

Then we will create a Functional Component "PrivateRoute" which accepts props and returns a stencil-route. This route itself has a routeRender which checks for auth. If auth fails it redirects to a login page or whatever we supply as failureRedirect.

And finally we will use this new Functional Component like a normal stencil-route.

Step 4. Create a redirect

There are two different approaches for redirecting using stencil-router. First is declarative redirect via stencil-router-redirect and the second is programmatically redirect via "our lovely" RouterHistory API. We will go over these and try to identify which one fits our use case.

Reacting to application state

In this example, we'll use declarative redirect by using stencil-route-redirect. Let's say we have an application or component state that requires a redirect. This example shows how we'll implement that:

Responding to a user action

The second example shows how we can create a redirect based on user actions. So we'll use RouterHistory. Let's say we want to redirect the user to a page in case of successful login otherwise do something else:

Step 5. Create a Not Found route

It's mandatory to have a Not Found page in your application to show it on a broken link or an incorrect URL. Thanks to Stencil Team, this approach is very straightforward.

We will use the stencil-route-switch which allows us to group multiple routes in an ordered manner. If the first doesn't match it will try the next in the list.

The trick is to create a route at the end of the list that does not have a specified URL. This tells the router to match on any URL. Here's an example:

Step 6. Inject history into a deep component

This is something which many of us was waiting for, sometimes when you needed to track pages and send events on Google Analytics (or other services) it was quite hard to approach that.

I even made a temporary Stencil Plugin for listening pages events but now we can use High Order Function - injectHistory.  My plugin works just as well because I'm using the same approach - the unique difference is just implementation, find more about the differences in the above link.

The injectHistory function accepts a component and then passes history as a prop. Then, we @Watch location changes with newValue and oldValue arguments:

Note that currently you must have an attribute with the @Element() decorator.


No doubts that Stencil Team invests a lot of time in this toolchain - as they name it, which allows generating small, blazing-fast, and 100% standards-based Web Components that run in every browser. If you haven't tried it yet I would suggest you try it as Stencil Router has already everything to run into a small or big application.

I'll keep an eye on it and will update this article every-time when there are other features.