How to Use React Router with Layouts: A New Approach

Using Array to Make Router in a Simple React App

image

For one of my simple projects, I decided to improve the readability of my code and make the next person who works on my code happy! :)

When I searched on Google about how to make a route I completely got confused and lost my main goal which was the improvement of readability.
All of the tutorials that I found, were pretty similar to the official react-router document.

A simple example of react-router:

image

Skip <Home/> , <About/>, <Dashboard/> components for now.

The code above is so clear with good readability.

But what if I want to use a layout with a component?

As far as I know, we have two options for using layouts:

  1. Making every component wrapped by layout separately
  2. Wrapping all routes that you want to use layout with layout component (I prefer the first way, I'm not so comfortable with the second one)

Option one would be something like this:

image

We Must do this for All Component that Wants to Use Layout

Then use them like this:

image

Skip <AnotherComponent/>, I just want to show you how to wrap and use them.

And second is something like this:

image

And use them like this:

image

In both ways, <SomeLayout> is something like this:

image

As you can see, this component combines all children and show one of them by using a Switch and Router, but it doesn't have good readability. Should I use this spaghetti code every time I need routing in my project?
(You can see some solutions on this link)

After talking to my teammates, they suggested I put all routes in an array and use the map function to make routes (it's easier to read and develop).

So instead of App.js in both above examples, we use this method:

image

In the picture above:

  1. Create an array (routes) of the object, the object has some property related to the Route component.

  2. Loop through the array of the routes and place them in (convert all elements from routes array to Route component from react-router-dom and move them into <routeComponent/>).

  3. Finally use the routeComponent that was generated in the second step (full example here, references are here).

It looks good but still needs to wrap all components with layout separately. :(

I think it could have been better if we use an object for all routes, and the object includes all routes and their properties like path, exact, layout, component

Imagine if we were able to convert this object to a real routing system:

image

I think it's the best way to define routes in a simple react project, but how to do this?

All we know is that we have to use a map to iterate through the array and return some component with some property…

We know that parent's layout had to be used in sub-routes (in this way, we define sub-route by one level in modules property).

For example, Admin.newProduct component inherits adminLayout from his parent.

Also, the path for newProduct is something like this:

http://www.site.com/admin/new_product

So we need to concatenate parent paths with children's paths.

All we know is we have to create some function component that returns the array of routes

Then use this component in this way:

image

So, we have to create a function component and name it RouteCombiner and receive props:

import React from "react";
import {} from "react-router-dom"; //Import Something Later from RRD
export default function RouteCombiner(props) {
  return;
  <>//Do Something With Props</>;
}

RouteCombiner Component receives PrivateRoute component (if you don't know about the private route, read this page) and routes object as props.

In RouteCombiner:

We must destructing some property (Read This If You Don't Know What Is Destructing), We need PrivateRoute a_nd _routes object. Then we must make another object that contains all generated route components and finally return that wrapped by the switch (You Can Use Switch In app.js when using this component Instead Of Here).

  1. Make loop through routes
  2. Make ComponentWithLayout Component t_hat contains _component wrapped by layout (we can make default value if layout doesn't exist)
  3. Check if the route has a Private attribute or not, if the Private attribute exists, return PrivateRoute Component that we send as props. If the Private attribute does NOT EXIST, return Route Component that was imported from RRD (react-router-dom).
  4. In both ways, if the modules property exists, make another loop and iterate through the modules array.

1:

image

2:

image

3:

image

That's all. Now we can use Layout and Path easily with one object but we forgot something. What about modules (modules stand for all children routes)?

If we want to return children's routes, there is some change in _RoutesMap.
_We return only one Route (Or Private Route) Component. If we need to return children, we have to return an array that contains the main Route and its children.

For the 4th step:

image

It's done. :)

It may sound difficult but imagine you are the person who has to use this code for Routing System.

Finally, this code is only for simple projects that won't Need SSR (Server-Side Rendering). Because both After.js and Next.js have their own routing scheme…and maybe some performance issues.

Full Example On my Sandbox

Happy Coding! 😜

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics