Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React router best practices for nested navigation?

I am building a React application, and using React Router for managing routing. The information architecture of the application can be represented as follows:

 - App
     - Projects
         - Project 1
             - Objects
               - Object 1
               - Object 2
               - etc...
             - Collaborators
         - ...
     - Services
     - Users

The UI of the application would look something like this, when looking at a route such as /#/projects/1/components/1

-----------------------------------------------------------
|            | Home > Projects > 0 > Object > 1           |
|  Home      |--------------------------------------------|
|            |                                            |
|  Projects  |   Object 1                                 |
|            |                                            |
|  Services  |   Blah blah blah                           |
|            |                                            |
|  Users     |                                            |
|            |                                            |
-----------------------------------------------------------

Note that for any given route shown in the information architecture scheme above, the view should be rendered in the body section (where 'Component 1' is rendered in the diagram above).

Now I will describe how I have been wrongly implementing this in React using React Router:

I have been using PlainRoutes to define my routes. Here is a short example of how a route is defined:

const routes = [
    {
        path: '/',
        component: App,
        name: 'Home',
        childRoutes: [
          // /projects
          {
              path: 'projects',
              component: Projects,
              name: 'Projects'
          },
          {
              path: 'projects/:projectid',
              component: ProjectDetails,
              name: 'Project Details',
              childRoutes: [
                  {
                       path: 'objects',
                       component: Objects,
                       name: 'Objects'
                  },
                  {
                      path: 'objects/:objectid',
                      component: ObjectDetails,
                      name: 'Object Details'
                  },
                  {
                      path: 'collaborators',
                      component: Collaborators,
                      name: 'Collaborators'
                  }
              ]
          },
          // /services
          {
              path: 'services',
              component: Services,
              name: 'Services'
          },
          // /users
          {
              path: 'users',
              component: Users,
              name: 'Users'
          }
      ]
   }
];

which then get fed into the React Router component, like this: <Router routes={routes}></Router>

Doing this sort of worked. When I would attempt to navigate to:

/#/projects

I would see the Projects component rendered in the body of the app.

When I would attempt to navigate to:

/#/projects/1

I would see the ProjectDetail component rendered in the body of the app.

However, when I would attempt to navigate to:

/#/projects/1/objects

I would still see the ProjectDetail component rendered in the body of the app. I am not sure why the router would just stop when the /projects/:projectid parameter was resolved, and not continue to render components assigned to the /projects/:projectid/objects route.

I think that the problem was that I was using React Router in the wrong way. Child routes are supposed to be physically nested inside their parent components - not just logically nested. At least, I think that is the problem. Clearly, I am a bit confused as to how React Router is intended to be used - especially the concept of childRoutes.

The question then is - how to use React Router to give the application the hierarchical structure that I am seeking, as outlined above? I want the router to be aware of the deeply nested structure of the application (for things like breadcrumbs and navigation), but I don't want to physically nest the components inside one another. What are best practices here?

like image 452
Jeff Fohl Avatar asked Jul 27 '16 01:07

Jeff Fohl


People also ask

Can you have nested routes react Router?

Routes can be nested inside one another, and their paths will nest too (child inheriting the parent).

How do you handle nested routes in react?

Now, the last thing you need to do is tell React Router where in the parent Route ( Messages ) should it render the child Route ( Chats ). To do this, you use React Router's Outlet component. If the app's location matches the nested Route 's path , this Outlet component will render the Route 's element .


1 Answers

Considering that you do not want to show both ProjectDetails and Objects at the path /#/projects/1/objects, then you do not want to nest these routes.

childRoutes: [
      // /projects
      {
          path: 'projects',
          component: Projects,
          name: 'Projects'
      },
      {
          path: 'projects/:projectid',
          component: ProjectDetails,
          name: 'Project Details',
      },
      {
          path: 'projects/:projectid/objects',
          component: Objects,
          name: 'Objects'
      },
      {
          path: 'projects/:projectid/objects/:objectid',
          component: ObjectDetails,
          name: 'Object Details'
      },

You would nest routes only if you were intending Objects to be populated inside this.props.children of ProjectDetails.

like image 127
azium Avatar answered Oct 24 '22 10:10

azium