Home > Enterprise >  What are the advantages of configuration based routing over component based routing with react route
What are the advantages of configuration based routing over component based routing with react route

Time:12-22

Prior to react-router 6.4, I was happily declaring my routes using the <Routes> and <Route> components. Wherever I wanted some route-dependent rendering, I could use these 2 components. I was able to nest routes, again by using the <Routes> and <Route> components in a nested component. I was also able to even use multiple Routes containers next to each other in 1 component.

I like this a lot because it keeps things small, nested routes can be handled in the nested component and don't need to bloat the root component. But most of all I like it because seeing the routes in your code where they actually will be rendered makes the code very readable and easy to visualize for me.

Now with react-router 6.4 it seems like they are moving more to a configuration based style of routing, where you define all routes on a root level. In some interviews it's clear that the maintainers are proud that they can now define nested routes on a root level. https://reactrouter.com/en/main/start/overview#nested-routes With that approach, you need to use the <Outlet/> component in spots where you want to render the nested route. When reading the code you to cross reference those Outlet locations with the configuration on the root level to figure out what is rendered where, which makes things much harder to visualize mentally.

So here's my question: what are the advantages of using such a configuration approach. Any guesses to why the maintainers are taking this road?

CodePudding user response:

Clarifications

  • First, since the introduction of react-router@6 you could use a routes configuration via the useRoutes hook or just use the RRD components and define the JSX for them. This is the "configuration based" vs "component based" routing you describe. It's nothing new in RRDv6.4.

    Configuration Example:

    import { useRoutes } from 'react-router-dom';
    
    const routes = [
      {
        element: <Layout />,
        children: [
          {
            path: "/foobar",
            element: <FooBar />
          },
          {
            path: "/foo",
            element: <Foo />
          },
          {
            path: "/bar",
            element: <Bar />
          },
        ],
      },
      {
        path: "/",
        element: <Home />
      },
    ];
    
    const App = () => {
      const appRoutes = useRoutes(routes);
      return appRoutes;
    };
    

    Component Example:

    import { Routes, Route } from 'react-router-dom';
    
    const App = () => (
      <Routes>
        <Route element={<Layout />}>
          <Route path="/foobar" element={<Foobar />} />
          <Route path="/foo" element={<Foo />} />
          <Route path="/bar" element={<Bar />} />
        <Route>
        <Route path="/" element={<Home />} />
      </Routes>
    );
    

    I believe somewhere in the older RRD docs outright stated that the Routes component was implemented using the useRoutes hook under-the-hood by converting the JSX you pass as children into a routes configuration object.

  • Second, what you are describing as "nested routes" are actually called descendent routes. Nested routes on the other hand are Route components directly rendering other Route components that render their content into the Outlet of their parent route.

    Descendent routes are good for code/route splitting.

Question

So here's my question: what are the advantages of using such a configuration approach. Any guesses to why the maintainers are taking this road?

What RRDv6.4 introduced was a new Data API which uses new Data Routers. See Picking a Router. Along with the new Data Routers came an updated Route component with a bunch of new props/functionality to be used within these new Data Routers. Now herein lies the rub. In order for the Route components to take advantage of the new Data APIs (action, errorElement, loader, and shouldRevalidate props) they necessarily need to be defined/configured when creating the Data Router. It doesn't matter if you use a routes "configuration" object with createBrowserRouter or use JSX with both createBrowserRouter and the createRoutesFromElements utility, all the routes that need the Data APIs need to be declared here.

The "advantage" is that you can use the new Data APIs with these routes. Of course the library maintainers are going to advertise and highlight their newest products and features.

AFAIK, the Data APIs don't currently work with descendent routes because these can be dynamic and there's not an easy way for a Route component to know what descendent Route components might be rendered under it in its sub-ReactTree at run-time. This is why nested routes are paramount; it's trivial to setup and maintain the overhead of the Data APIs when you know ahead of time exactly what routes can be rendered and what data they may manage.

  • Related