There are many ways to approach routing in client-side apps. Frameworks like Android provide powerful but also complex and sometimes restrictive routing mechanisms. The same applies to full-fledged routing libraries in the frontend like React Router.
The good news is that you can write your own routing layer that is simpler without giving up control: Routing that fits your app—not the other way around!
This is the live result:
Let’s start by defining the Feed route:
comp are obvious. With
link you have type-assisted reverse routing. In the lifecycle function
activate , you update global state and perform API requests. The dependency
store is your central state management and action control panel. In the last line, you add
FeedRoute to your route registry
The cool thing about
FeedRoute is that everything relevant for routing to/from the Feed screen is defined in one place. Plus, you don’t need a container component for performing API requests.
Here’s how you render the current route:
The observable property
store.route contains the current route. In your route registry
store.routes you find the corresponding route definition. So, you know which component to render. If you’re on
/ the component will be
<FeedScreen/>. By being an observer,
App rerenders whenever the observable
That’s the gist!
Getting it set up
Aside: Although a routing library is not required, I do recommend router5. It gives you a more convenient API (+ hooks and utilities) than the browser’s native one.
The router5 plugin definition:
A router5 plugin implements lifecycle functions. On a successful transition, you deactivate the previous route. Then you set
store.route to the next route and activate the next route. Deactivation performs cleanup. Activation performs API requests and other initialization logic. The rest of the code is router5 API specific.
Here are the relevant parts from
The selected feed is derived from the URL. There is no duplication of state thanks to MobX’s propagation power!
Aside: I use a special fetching helper which will be a topic for another article.
In my own HackerNews client (live), a history stack keeps track of the visited routes. It is used to render the screens on top of each other. All but the top-most screen have
display set to
none. This makes going back to the previous screen on mobile devices much faster!
My router also performs view state restoration. Think scroll position. But you can just as well keep it as minimal as shown here. Remember, you are in control of routing: do it in a way best suited to your app. See also React Router’s scroll restoration discussion and router5’s loading async data dicussion.
The presented approach is inspired by:
- How to decouple state and UI (you don’t need componentWillMount)
- A different approach to routing in Single-Page Applications
If you enjoyed this article, please recommend and share. Happy Routing!