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:
- Use layout routes and nested
Route
components. - Render routed components that render descendent routes in another
Routes
component wrapping descendentRoute
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>
);
};