Skip to content

Commit 1bae6af

Browse files
authored
Tweak 02_routing for fluency
1 parent 3935b87 commit 1bae6af

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

packages/overmind-website/guides/intermediate/02_routing.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
With Overmind you can use whatever routing solution your selected view layer provides. This will most likely intertwine routing state with your component state, which is something Overmind would discourage, but you know... whatever you feel productive in, you should use :-) In this guide we will look into how you can separate your router from your components and make it part of your application state instead. This is more in the spirit of Overmind and throughout this guide you will find benefits of doing it this way.
44

5-
We are going to use [page js](https://www.npmjs.com/package/page) as the router and we will look at a complex routing example where we open a page with a link to a list of users. When you click a user in the list we will show that user in a modal with the url updating to the id of the user. In addition we will present a query parameter that reflects the current tab inside the modal.
5+
We are going to use [page.js](https://www.npmjs.com/package/page) as the router and we will look at a complex routing example where we open a page with a link to a list of users. When you click on a user in the list we will show that user in a modal with the URL updating to the id of the user. In addition we will present a query parameter that reflects the current tab inside the modal.
66

7-
We will start with a simple naive approach and then we are going to tweak our approach a little bit for the optimal solution.
7+
We will start with a simple naïve approach and then tweak our approach a little bit for the optimal solution.
88

99
## Set up the app
1010

1111
Before we go into the router we want to set up the application. We have some state helping us express the UI explained above. In addition we have three actions.
1212

1313
1. **showHomePage** tells our application to set the current page to *home*
1414
2. **showUsersPage** tells our application to set the current page to *users* and fetches the users as well
15-
3. **showUserModal** tells our application to show the modal by setting an id of a user passed to the action. This action will also handle the switching of tabs later
15+
3. **showUserModal** tells our application to show the modal by setting an id of a user passed to the action. This action will also handle the switching of tabs later.
1616

1717

1818
```marksy
@@ -21,13 +21,13 @@ h(Example, { name: "guide/routing/setup" })
2121

2222
## Initialize the router
2323

24-
**Page js** is pretty straight forward. We basically want to map a url to trigger an action. To get started let us first add Page js as an effect and let us take the opportunity to create a custom API. When a url triggers we want to pass the params of the route to the action linked to the route:
24+
**Page.js** is pretty straightforward. We basically want to map a URL to trigger an action. To get started, let us first add Page.js as an effect and take the opportunity to create a custom API. When a URL triggers we want to pass the params of the route to the action linked to the route:
2525

2626
```marksy
2727
h(Example, { name: "guide/routing/effect" })
2828
```
2929

30-
Now we can use Overminds **onInitialize** to configure the router. That way the initial url triggers before the UI renders and we get to set our initial state.
30+
Now we can use Overmind's **onInitialize** to configure the router. That way the initial URL triggers before the UI renders and we get to set our initial state.
3131

3232
```marksy
3333
h(Example, { name: "guide/routing/pagejs" })
@@ -37,19 +37,19 @@ Take notice here that we are actually passing in the params from the router, mea
3737

3838
## The list of users
3939

40-
When we now go to the list of users the list loads up and is displayed. When we click a user the url changes, our **showUser** action runs and indeed, we see a user modal.
40+
When we now go to the list of users the list loads up and is displayed. When we click on a user the URL changes, our **showUser** action runs and indeed, we see a user modal.
4141

4242

4343
```marksy
4444
h(Example, { name: "guide/routing/users" })
4545
```
4646

4747

48-
But what if we try to refresh now... we get an error. The router tries to run our user modal, but we are on the frontpage. The modal does not exist there. We want to make sure that when we open a link to a user modal we also go to the actual user list page.
48+
But what if we try to refresh now... we get an error. The router tries to run our user modal, but we are on the front page. The modal does not exist there. We want to make sure that when we open a link to a user modal we also go to the actual user list page.
4949

5050
## Composing actions
5151

52-
A straight forward way to solve this is to simply also change the page in the **showUserModal** action, though we would like the list of users to load in the background as well. The logic of **showUsers** might also be a lot more complex and we do not want to duplicate our code. When these scenarios occur, where you want to start calling actions from actions, it indicates you have reached a level of complexity where a functional approach might be better. Let us look at how you would implement this both using a functional approach and a plain imperative one.
52+
A straightforward way to solve this is to simply also change the page in the **showUserModal** action, though we would like the list of users to load in the background as well. The logic of **showUsers** might also be a lot more complex and we do not want to duplicate our code. When these scenarios occur where you want to start calling actions from actions, it indicates you have reached a level of complexity where a functional approach might be better. Let us look at how you would implement this both using a functional approach and a plain imperative one.
5353

5454
### Imperative approach
5555
```marksy
@@ -65,9 +65,9 @@ When running actions from within other actions like this it will be reflected in
6565
h(Example, { name: "guide/routing/compose" })
6666
```
6767

68-
By splitting up all our logic into operators we were able to make our actions completely declarative and at the same time reuse logic across them. The *operators* file gives us maintaineable code and the *actions* file gives us readable code.
68+
By splitting up all our logic into operators we were able to make our actions completely declarative and at the same time reuse logic across them. The *operators* file gives us maintainable code and the *actions* file gives us readable code.
6969

70-
We could actually make this better though. There is no reason to wait for the user of the modal to load before we load the users list in the background. We can fix this with the **parallel** operator. Now the list of users and the single user loads at the same time.
70+
We could actually make this better though. There is no reason to wait for the user of the modal to load before we load the users list in the background. We can fix this with the **parallel** operator. Now the list of users and the single user load at the same time.
7171

7272
```marksy
7373
h(Example, { name: "guide/routing/parallel" })
@@ -77,21 +77,21 @@ Now you are starting to see how the operators can be quite useful to compose flo
7777

7878
## The tab query param
7979

80-
**Page js** also allows us to manage query strings, the stuff after the **?** in the url. Page js does not parse it though, so we introduce a library which does just that, [query-string](https://www.npmjs.com/package/query-string). With this we can update our router to also pass in any query params.
80+
**Page.js** also allows us to manage query strings, the stuff after the **?** in the url. Page.js does not parse it though, so we introduce a library which does just that, [query-string](https://www.npmjs.com/package/query-string). With this we can update our router to also pass in any query params.
8181

8282

8383
```marksy
8484
h(Example, { name: "guide/routing/query" })
8585
```
8686

8787
### Imperative approach
88-
We now also handle the received tab param and make sure that when we change tabs we do not load the user again. We only want to load the user when there is no existing user or if the user has changed.
88+
We now also handle the received tab parameter and make sure that when we change tabs we do not load the user again. We only want to load the user when there is no existing user or if the user has changed.
8989

9090
```marksy
9191
h(Example, { name: "guide/routing/tab_imperative" })
9292
```
9393

94-
### Functionl approach
94+
### Functional approach
9595
Now we can add an operator which uses this **tab** query to set the current tab and then compose it into the action. We also add an operator to verify if we really should load a new user.
9696

9797
```marksy
@@ -100,6 +100,6 @@ h(Example, { name: "guide/routing/tab" })
100100

101101
## Summary
102102

103-
With little effort we were able to build a custom "**application state first**" router for our application. Like many common tools needed in an application, like talking to the server, local storage etc., there are often small differences in the requirements. And even more often you do not need the full implementation of the tool you are using. By using simple tools you can meet the actual requirements of the application more "head on" and this was an example of that.
103+
With little effort we were able to build a custom "**application state first**" router for our application. Like many common tools needed in an application, like talking to the server, localStorage etc., there are often small differences in the requirements. And even more often you do not need the full implementation of the tool you are using. By using simple tools you can meet the actual requirements of the application more "head on" and this was an example of that.
104104

105-
We also showed off how you can solve this issue with an imperative approach or go functional. In this example functional is probably a bit overkill as there is very little composition required. But if your application needed to use these operators many times in different configurations you would benefit more from it.
105+
We also showed how you can solve this issue with an imperative approach or go functional. In this example functional is probably a bit overkill as there is very little composition required. But if your application needed to use these operators many times in different configurations you would benefit more from it.

0 commit comments

Comments
 (0)