3

I'm building an app with React and I'm using React routes.

I have 3 main routes:

  • If the user is logged in, show Dashboard
  • If the user is not logged in, show SignIn page
  • If the user clicks on ForgotPassword on the SignIn page, change url and show ForgotPassword page

index.js

ReactDOM.render(
    <Provider store={store}>
        <BrowserRouter>
            <Suspense fallback={<div>Loading...</div>}>
                <div>
                    <Switch>
                        <Route path="/" component={App} />
                        <Route path="/login" component={Login} />
                        <Route path="/forgotPassword" component={ForgotPassword} />
                    </Switch>
                </div>
            </Suspense>
        </BrowserRouter>
    </Provider>,
  document.getElementById('root')
);

App.js

{this.props.location.pathname === "/" && <Dashboard />}
<Route exact path="/users" component={Users} />
<Route path="/users/:id" component={UserPage} />
{!authenticated && <Redirect to="/login" />}

When I try to open "/", it redirects to "/login" but it doesn't render Login component.
When I replace {!authenticated && <Redirect to="/login" />} with {!authenticated && <Login>} it renders the component properly, but it doesn't change the url and it won't show the ForgotPassword page.

How do I set this properly?

1
  • Did you tried <Route exact path="/" component={App} /> with exact in all routes? Commented Aug 2, 2021 at 9:44

3 Answers 3

1

You'll need to reorder your switch:

<Switch>
    <Route path="/login" component={Login} />
    <Route path="/forgotPassword" component={ForgotPassword} />
    <Route path="/" component={App} />
</Switch>

Then, maybe make that App something like

{!authenticated ? <Redirect to="/login" /> : (
  <Switch>
    <Route path="/users/:id" component={UserPage} />
    <Route exact path="/users" component={Users} />
    <Route path="/" component={Dashboard />
  </Switch>
)}

(though it could be simpler to just keep all routes in the top-level router/switch)

Sign up to request clarification or add additional context in comments.

Comments

1

Problem is order of the Route components and the use of Switch component.

When you redirect to /login, Switch will render the first matching route; for the /login route, / route also matches.

This is why Login component isn't rendered. App component is rendered for both / and /login routes.

Solution

Couple of solutions to this problem are described below:

exact prop

One way to solve the problem is to use the exact prop. This will ensure that / route doesn't matches /login BUT it will cause another problem: nested routes inside App component won't be rendered. This is because for nested route to be rendered, parent route also needs to be rendered.

Re-order the Route components

Another solution is to change the order of your routes as:

<Switch>
   <Route path="/login" component={Login} />
   <Route path="/forgotPassword" component={ForgotPassword} />
   <Route path="/" component={App} />
</Switch>
                        

Comments

0

You have to use render prop instead of component and the render prop give you the ability to do some checks and return the appropriate component

<Route render={(props) => !isAuth ? <Redirect to='/signin' /> : <Component {...props} /> } />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.