3

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.

Rikin
  • 5,351
  • 2
  • 15
  • 22
ousmane784
  • 306
  • 1
  • 17
  • Right now it just stays at /profile and doesnt redirect automatically – ousmane784 Mar 24 '21 at 15:57
  • It seems like a problem when using react fragments <>> it doesnt work in a switch. Any workarounds? – ousmane784 Mar 24 '21 at 16:11
  • Switch can only have Route as a direct children. You can remove conditional and fragments and keep all routes exposed. Redirect should catch if none of the prior route matches. – Rikin Mar 24 '21 at 16:13
  • You could return and spread (`...`) an array of react elements (e.g. routes) rather than wrapping them in a fragment. – DBS Mar 24 '21 at 16:21

3 Answers3

1

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.

DBS
  • 9,110
  • 4
  • 35
  • 53
1

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>
  )
}

Edit:

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`} />
Ajeet Shah
  • 18,551
  • 8
  • 57
  • 87
0

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>
Dharman
  • 30,962
  • 25
  • 85
  • 135
crispengari
  • 7,901
  • 7
  • 45
  • 53