Home > Enterprise >  Changing from v5 to v6, how to make it work with relative paths?
Changing from v5 to v6, how to make it work with relative paths?

Time:09-22

My application has scenarios where we need several routes to "pass" through a component to only then render the specifics, not only that but also situations where something is shown for the "parent" route and then split for the children...

It is imperative to note that we don't have a single "route config" file, and instead our routes are where we need them.

This was possible with v5, but I am very confused about how to get this accomplished with the new version.

So, currently we have stuff such as:

App.js

function App = () => {
  return (
    <Switch>
      <Route exact path={['/', '/2', '/more-info']} component={Login} />
      <Route path="/(main|settings|notifications)" component={AuthenticatedUser} />
      <Redirect from="*" to="/404" />
    </Switch>
  );
}

AuthenticatedUser.js

function AuthenticatedUser= () => {
  {... lots of common code}
  return (
    <div>
      {...common html}
      <Switch>
        <Route exact path="/main" component={Main} />
        <Route path="/settings" component={Settings} />
        <Route path="/notifications" component={Notifications} />
      </Switch>
    </div>
  );
}

Settings.js

function Settings= () => {
  {... lots of common code}
  return (
    <div>
      {...common html}
      <Switch>
        <Route exact path="/settings/basic" component={Basic} />
        <Route exact path="/settings/notifications" component={Notifications} />
      </Switch>
    </div>
  );
}

Now, with the relative from the parent, I am not able to get the same structure, I am also confused about how to get the routes split into separate files not even talking about the regex situation that I am guessing the solution is to duplicate the lines as many times as I have items in that regex...

CodePudding user response:

You have basically 2 options when it comes to declaring the routes and sharing common UI:

  1. Use layout routes and nested Route components.
  2. Render routed components that render descendent routes in another Routes component wrapping descendent Route components.

Using layout and nested routes

Convert AuthenticatedUser into a layout route. Layout routes render an Outlet for nested routes to render their matched element into.

import { Outlet } from 'react-router-dom';

function AuthenticatedUser = () => {
  {... lots of common code}
  return (
    <div>
      {...common html}
      <Outlet />
    </div>
  );
};

Convert Settings also into a layout route component.

import { Outlet } from 'react-router-dom';

function Settings = () => {
  {... lots of common code}
  return (
    <div>
      {...common html}
      <Outlet />
    </div>
  );
};

App

import { Routes, Route, Navigate } from 'react-router-dom';

function App = () => {
  return (
    <Routes>
      <Route path="/" element={<Login />} />
      <Route path="/2" element={<Login />} />
      <Route path="/more-info" element={<Login />} />

      <Route element={<AuthenticatedUser />}>
        <Route path="/main" element={<Main />} />

        <Route path="/settings" element={<Settings />}>
          <Route
            path="basic" // "/settings/basic"
            element={<Basic />}
          />
          <Route
            path="notifications" // "/settings/notifications"
            element={<Notifications />}
          />
        </Route>

        <Route path="/notifications" element={<Notifications />} />
      </Route>

      <Route path="*" element={<Navigate to="/404" replace />} />
    </Routes>
  );
};

Using descendent routes

Here the parent routes need to render their route path with a trailing "*" wildcard matcher so descendent routes can also be matched. Descendent Routes components build their route paths relative to their parent Route path. I'd still suggest using AuthenticatedUser as a layout route for ease, otherwise you'll have a lot of code duplication since you'd need to wrap each route individually.

App

import { Routes, Route, Navigate } from 'react-router-dom';

function App = () => {
  return (
    <Routes>
      <Route path="/" element={<Login />} />
      <Route path="/2" element={<Login />} />
      <Route path="/more-info" element={<Login />} />

      <Route element={<AuthenticatedUser />}>
        <Route path="/main" element={<Main />} />
        <Route path="/settings/*" element={<Settings />} />
        <Route path="/notifications" element={<Notifications />} />
      </Route>

      <Route path="*" element={<Navigate to="/404" replace />} />
    </Routes>
  );
};

Settings

import { Routes } from 'react-router-dom';

function Settings = () => {
  {... lots of common code}
  return (
    <div>
      {...common html}
      <Routes>
        <Route
          path="/basic" // "/settings/basic"
          element={<Basic />}
        />
        <Route
          path="/notifications" // "/settings/notifications"
          element={<Notifications />}
        />
      </Routes>
    </div>
  );
};
  • Related