Reputation: 446
I have a page that has tabs on it. When I navigate to the page on my app I push to the base app. Ie. "/profile".
This is my profile component, the page that gets called.
<Profile>
<Switch>
<Route exact path={`${path}/feed`} component={Feed} />
{profileId !== null && (
<>
<Route exact path={`${path}/friends`} component={Friends} />
<Route exact path={`${path}/locations`} component={Locations} />
<Route exact path={`${path}/blockedlist`} component={BlockedList} />
</>
)}
<Redirect from={path} to={`${path}/feed`} />
</Switch>
</Profile>
The redirect never gets run. When I remove the check if profileId !== null
then it works. Basically when I load the page it will be at path /profile
then this component should handle the redirect to /feed
on initial load.
Upvotes: 3
Views: 214
Reputation: 9959
If you need to avoid wrapping an element (like with these Route's), you can spread an array of JSX elements instead, like this:
<Switch>
<Route exact path={`${path}/feed`} component={Feed} />
{...(profileId !== null ? [
<Route exact path={`${path}/friends`} component={Friends} key='friends' />,
<Route exact path={`${path}/locations`} component={Locations} key='locations' />,
<Route exact path={`${path}/blockedlist`} component={BlockedList} key='blockedlist' />
]: [])}
<Redirect from={path} to={`${path}/feed`} />
</Switch>
Broken down, what this is doing is:
{
...( // The spread operator will expand the array it's given into its components
conditional ? // Check your condition
[routes]: // If it's true, return the routes
[] // If not, return no routes
)
}
Since it's returning an array into the render function, each item should have a key
(Which is used by react to optimise the re-renders) so I've set each route to have part of it's path name as the key as these should be unique.
Upvotes: 1
Reputation: 19813
All children of a <Switch>
should be <Route>
or <Redirect>
elements. See the docs.
So, you can refactor your nested routes (in Profile
component) like this:
function Profile() {
const { path } = useRouteMatch()
return (
<Switch>
<Route exact path={`${path}/feed`} component={Feed} />
<Route
render={(props) =>
profileId !== null ? (
<Switch>
<Route exact path={`${path}/friends`} component={Friends} />
<Route exact path={`${path}/locations`} component={Locations} />
<Route exact path={`${path}/blockedlist`} component={BlockedList} />
</Switch>
) : (
<Redirect to={`${path}/feed`} />
)
}
/>
<Redirect to={`${path}/feed`} />
</Switch>
)
}
You can also add a redirect at last inside inner i.e. 2nd Switch
above so that if user enter /profile
and profileId
is valid, it will redirect to /profile/friends
:
...
<Redirect to={`${path}/friends`} />
Upvotes: 1
Reputation: 9321
Wrap your switch statements with BrowserRouter object and remove fregments <>
and use div
try this;
import {BrowserRouter as Router } from 'react-router-dom'
<Profile>
<Router>
<Switch>
<Route exact path={`${path}/feed`} component={Feed} />
{profileId !== null && (
<div>
<Route exact path={`${path}/friends`} component={Friends} />
<Route exact path={`${path}/locations`} component={Locations} />
<Route exact path={`${path}/blockedlist`} component={BlockedList} />
</div>
)}
<Redirect from={path} to={`${path}/feed`} />
</Switch>
</Router>
</Profile>
Upvotes: 0