This is how the Switch
component works, it simply "renders the first child <Route>
or <Redirect>
that matches the location." The Switch
exclusively renders routes/redirects, e.g. only 1 can be matched and rendered. This is different than routes/redirects rendered just within a router component that inclusively renders anything that matches.
If you want to unconditionally render the Dashboard
then move its route outside the switch to exclude it from the Switch
.
Use the children
function prop to unconditionally render the route and then decide what to actually render. The Dashboard
component can be configured to remain mounted and conditionally render its own content.
Example:
const Dashboard = ({ isMatch }) => {
... dashboard business logic ...
return isMatch
? ( ... dashboard UI ... )
: null; // hidden
};
<AuthenticatedRoute
path="/dashboard"
session={session}
redirect="/"
children={({ match }) => <Dashboard isMatch={match} />}
/>
<Switch>
<Route exact path="/" render={this.renderRootRoute} />
<Route exact path="/lostpassword" component={LostPassword} />
<AuthenticatedRoute exact path="/profile" component={Profile} session={session} redirect="/" />
<AuthenticatedRoute path="/meeting/:meetingId" component={MeetingContainer} session={session} redirect="/" />
<Route component={NotFound} />
</Switch>
You may need to tweak the AuthenticatedRoute
component to correctly consume route component props. This allows passing any of the valid Route
component props to AuthenticatedRoute
to be passed on to Route
, e.g. path
, component
, render
, children
, exact
, etc....
Example:
const AuthenticatedRoute = ({ redirect, session, ...props }) => {
return /* auth condition using session */
? <Route {...props} />
: <Redirect to={redirect} />;
};
Similarly, in react-router-dom@6
where the Routes
component replaced the Switch
component, it selects the single best match and renders it. The main difference between Routes
and Switch
though is that RRDv6 uses a route ranking system to select the best match instead of relying on the code maintainer to correctly order the routes in the Switch
by inverse order of path specificity. The same rules apply to when routed components are rendered though, e.g. when the route they are rendered on is the currently matched route, the routed component is mounted, otherwise it is unmounted.
Again, if you want to unconditionally render the Dashboard
component it should be rendered outside the Routes
on its own.
<Dashboard /> // *
<Routes>
<Route path="/" element={this.renderRootRoute} />
<Route path="/lostpassword" element={<LostPassword />} />
<Route element={<AuthenticatedRoute session={session} redirect="/" />}>
<Route path="/profile" element={<Profile />} />
<Route path="/meeting/:meetingId" element={<MeetingContainer />} />
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
* Note: You can update the Dashboard
component to use any internal condition to conditionally render any specific content, if necessary.
If you want the Dashboard
to render only with specific routes then create a layout route that renders it and an Outlet
for nested routes.
Example:
import { Outlet } from 'react-router-dom';
export const DashboardLayout = () => (
<>
<Dashboard />
<Outlet />
</>
);
For example, if you wanted Dashboard
to only render along with the authenticated routes:
<Routes>
<Route path="/" element={this.renderRootRoute} />
<Route path="/lostpassword" element={<LostPassword />} />
<Route element={<AuthenticatedRoute session={session} redirect="/" />}>
<Route element={<DashboardLayout />}>
<Route path="/profile" element={<Profile />} />
<Route path="/meeting/:meetingId" element={<MeetingContainer />} />
</Route>
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
The Dashboard
will remain mounted and rendered so long as one of its nested routes is being matched and rendered.