DEV Community

miguel-penaloza
miguel-penaloza

Posted on

The What, Why and How of React (Routers)

Hi, this is the second article about React fundamentals, today we’re going to talk about one of the most important parts of any web application, The Routing. Every site has a particular way to deal with his navigation.I will try to explain a different approach and try to give you a more clear idea of when you have to use a library and when it's better do it by yourself.

What's Routing?
The routing is basically how you're going to move inside your website. You can start with an index, a home or a dashboard page, then each section of your site will have a domain based on what you want to display, you can have something like this:

  • The name of the resource of domain: e.g, for a page with the list of books, you will have something like this: books.
  • The details of the resource: To see the details of one specific resource in this case a book, you will have a url like: books/{id}.
  • To Create, Manage, Edit, etc. a resource: You can add a description of what do you want to do next to the domain, such as, to create a new book, you can use: books/create and for edit you can use: books/edit.

This’s the most used pattern and works all right. These sites can grow up exponentially, and this is superb because this will give you an idea of Domain and Ownership. Also usually, a domain become in a big module with several logic and with a particular way to navigate.

In almost all the tutorials and documentation of React, they recommend you create a SPA (Single Page Application), and what’s that? Well is just a page that can have inside domains, resources or even others SPAs.

Why routing in React?
The basic idea of a SPA is that you can have a full operative application, in just one page, with only one call to the server, without change url, or at least without to consume a new Page. In most of the React Apps, you have an Index.js, who start everything (redux, sagas, etc.), then you have a Magical component that decides which one of the infinitive number of components that you can have in your code is the one who should be rendered.

This Magical Component who decided which component needs to be rendered is what we can name Router in React.

React Router

The idea of having a SPA is that you can get everything what you need at the beginning, resources, images, components, etc. If you’re in the page books, you should not render a new full-page for the books/id, just change the component, and maybe consume a number of services with the information that you may need in the new page without reload the entire page, if we need information to render our page. A Router should provide some useful solutions that help us with our implementation, these are the minimal requirement that we expect of a Router:

  • Just change the component, not reload the entire page.
  • The state should be the same, change the route doesn't mean start over again.
  • Be able to move between all our pages.
  • The router should be able to know when return a specific page, a default page, a not found page, etc.
  • Should be able to consume the query params or any information provided in the url, in the best of the cases as a nice a beauty Object.

If we can build or use something that give us these functionalities, we will be able to build a good application that can grow up, and be as complete as you wish. Also, there’s a lot of discussion about file structure and navigation, is common that the domain give you a directory level in your code, you need to care avoid too much nesting. That’s why a good definition of your routing will help you to get a better application.

How use a Router in React?
Here’s the tricky part, as we say before routing is one of the most important parts in our development, basically the navigation flow is what give us the identity of our site, this flow should be natural, intuitive and accord with your business model.

Then, what should I use? A library? Build my own router? If I choose use a library, which one? If I found the library, what version? Sadly if you are in early version of React you will have your options, if you’re in a latest version you will have to use another one, even for the same library base on your React version you should use a oldest or latest version. The navigation in a site can be so custom that the perfect router is something that depends of what you want.

In the official documentation of React, they recommend a list of libraries, with a tinny comment. This’s common in the React documentation. They don’t give you opinions in this kind of themes, they just give some information and after that they just tell you try these options, hope something works for you, that is a real good thing, because they don’t marry with any library and give you the freedom to find what fits for you.

But also in almost all the React tutorials that you can find online they use React Router as the default router library depends of the year of the tutorial you will find that they use a specific version, you need to be careful with this, I’m not going to repeat these tutorials, I will let you here a list with what I think are the best in the web today.

  • Routing React Apps: The Complete Guide , This one is one of the best and complete, he talks at lot about dependencies, structure files, theoretical concepts and is fantastic to understand the details of the implementation.
  • React Trainning React Router , This one is a good one too, because they bring you the implementation and give you examples of almost all the Api that React Router provide us.
  • A Simple React Router v4, this’s excellent because is more practical, is like a mix of the 2 above. Also is for the latest version that works fine with React 16.
  • React Router Tutorial Official, Is the official documentation, you can be sure that this one should be the most accurate and updated of all.

What I will bring to you, is a simple example of how code it yourself, the idea is understand what is going on with all these libraries are doing, and don’t think in this as a magic thing and no one understand what’s going on.

The first thing that you need to understand is that the route is just a state, that will have the current path. In this example I will use an action that will change the current path to another one, no matter what we pass it to this action, that will be the current path. The first route taken is the one in the window.location, then we only can change the route using the push action.

// Action
import { createAction } from 'redux-actions';

export const push = createAction('PUSH');

// Reducer
import { handleActions } from 'redux-actions';

const { pathname } = window.location

export const routerState = {
    route: 'pathname'
};

export default handleActions({
    PUSH: (state, { payload }) =>
        Object.assign({}, state, {
            route: payload
        })
}, routerState);

Enter fullscreen mode Exit fullscreen mode

The reducer just handles the action, receive a new route and now that’s the current path, you can include more information in this state, like history, and of course more actions, like goBack, goToTheMainPage, goTo404, etc. All this depends of what is your navigation, for simple redirections this’s just fine.

After that we need 2 components, a Router that will handle the decision of which Route should be rendered and the Route that should be a simple component that the Router can read and understand.

import { Component, Fragment, createElement } from 'react';
import { connect } from 'react-redux';

// Route
export const Route = ({ component }) => createElement(component, this.props);

// Router
export const Router = ({ children, route }) => <Fragment>
    { children.find(childrenRoute => route === childrenRoute.props.path) }
</Fragment>

export const mapStateToProps = (state) => ({
    route: state.router.route
});

export default connect(mapStateToProps)(Router);
Enter fullscreen mode Exit fullscreen mode

As you can see here, the Route, just return the Component passed as props and the Router will have as a children all the Routes, then just return the one who match with the current path. The Router receive the current path when we connect the state with the props, and when someone dispatch the action push, our Router will refresh the Component based on that, with this we can navigate between pages without losing the state.

Note:the Fragment is just a fancy React component that I like to use, give you a wrapper without insert any element.
Note 2: The filter is straightforward, but you can extract in a more complex function based on how you want to handle the navigation on your site.
Note 3: You also can define in the Router, a default Route (like home, or 404) when the filter won’t find anything.
Note 4: Also, the Route in this example looks like is not doing anything, but you can include more logic there, that you don’t want to include in the real component, like special validation for the path, extra props that you may need. That’s why I create this Route

And then we have the implementation, here we have a BooksPage, a BooksDetails and a BooksCreate that are just components, with his own logic, and I don’t want to implement any kind of routing logic in this components, In this example we can go on and include as many routes as we want, this is very similar with the React Router implementation, but without all the others functions and components that they provide but we don’t need it right now if our navigation is no so complex.

export class Index extends Component {
    render() {
        return (
            <Router>
               <Route path=books component={BooksPage}/>
               <Route path=books/{id} component={BooksDetails}/>
            <Route path=books/create component={BooksCreate}/>
            </Router>
        );
    }
}

Enter fullscreen mode Exit fullscreen mode

And finally the last thing that we need, is how to change the route? Well from any part of your application you can just dispatch the action push with the new route like this:

dispatch(push(books/create));
Enter fullscreen mode Exit fullscreen mode

The reducer handle this dispatch, when the state changes the Router will update the page keeping our state without refresh the entire page. This router is raw and also there’s a lot of functionalities and logic that are missing (you need to realize that existing libraries already solve these problems), like the change of the url, handle the history, go back to the last page, but this implementation, do the most simple thing: navigate in a SPA.

Hope this helps you to understand what’s a Router, and help you with the decision of which Library use, and how deal with his implementation, also you can try to build it yourself and deal with all your specific requirements of your navigation flows.

What you need to realize is that develop a new Router for your site should not become in a try to reinvent the wheel, also if you decide include a existing library with his implementations, won't become our project in a monster that depends in so many things and you finish installing dependencies of the dependencies just to make one thing works as you want.

Really Hope you've enjoyed reading. See you in the next post.

InTheCodeWeTrust

Previous: The What, Why and How of React (High Order Components)

Top comments (1)

Collapse
 
theuserll profile image
L.L.

I was looking for this explanation for the past 2 days! Thank you!