Home > Back-end >  React: how to redirect some pages to a login page
React: how to redirect some pages to a login page

Time:12-24

I'm moving my first steps in react world and I'm stuck with a problem with authentication. I prepared a login page that is presented to the user when a token is empty. The page call a login web api (.netcore backend). When return the token the homepage is rendered. But if I want to present the homepage to all and only some page authenticated, I'm not able to resolve this problem.

My App.js file

function App() {
    const { token, setToken } = useToken();

      if (!token) {
          return <Login setToken={setToken} />
      }
 
    return (
        <Layout>
            <Route exact path='/' component={Home} />
            <Route path='/counter' component={Counter} />
            <Route path='/fetch-data' component={FetchData} />
            <Route path='/dashboard' component={Dashboard} />
            <Route path='/settings' component={Settings} />
        </Layout>
    );
}

export default App;

Where I have to move the Login component to authenticate Settings page (for example)? Thank you!

Update Thank you for answers, now I implemented Private and Public Route. Now my App.js is as follow

return (
    <Layout>
        <BrowserRouter>
            <Switch>
                <PublicRoute restricted={false} component={Home} path="/" exact />
                <PublicRoute restricted={true} component={Login} path="/signin" exact />
                <PrivateRoute component={Dashboard} path="/dashboard" exact />
            </Switch>
        </BrowserRouter>
    </Layout>

Layout is a component that display a NavMenu and a Container

  render () {
    return (
      <div>
        <NavMenu />
        <Container>
          {this.props.children}
        </Container>
      </div>
    );
  }

and NavMenu ha the links ...

<ul className="navbar-nav flex-grow">
                <NavItem>
                  <NavLink tag={Link} className="text-dark" exact to="/">Home</NavLink>
                </NavItem>
                <NavItem>
                  <NavLink tag={Link} className="text-dark" exact to="/dashboard">Dashboard</NavLink>
                </NavItem>
                <NavItem>
                  <NavLink tag={Link} className="text-dark" exact to="/signin">Signin</NavLink>
                </NavItem>
              </ul>

...

When I click on a link in the Navbar nothing happens. In the url appear the destination link but browser doesn't load it. I need to press return to go to the page. I cannon unserstand why... Can you help? Thanks

CodePudding user response:

Use HOC for Private and Public routes and wrap all routes inside this hoc. PrivateRoute component is the blueprint for all private routes in the application. If the user is logged in, go on and display the component in question; otherwise, redirect the user to sign-in page. Additionally, we can define the logic of isLogin utility function separately in utils folder.

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { isLogin } from '../utils';

const PrivateRoute = ({component: Component, ...rest}) => {
    return (

        // Show the component only when the user is logged in
        // Otherwise, redirect the user to /signin page
        <Route {...rest} render={props => (
            isLogin() ?
                <Component {...props} />
            : <Redirect to="/signin" />
        )} />
    );
};

export default PrivateRoute;

and the routes are like this :

import React, { Component } from 'react';
import './App.css';
import { BrowserRouter, Switch } from 'react-router-dom';
import Home from './components/Home';
import Dashboard from './components/Dashboard';
import SignIn from './components/SignIn';
import PrivateRoute from './components/PrivateRoute';
import PublicRoute from './components/PublicRoute';

class App extends Component {

  render() {
    return (
      <BrowserRouter>
        <Switch>
          <PublicRoute restricted={false} component={Home} path="/" exact />
          <PublicRoute restricted={true} component={SignIn} path="/signin" exact />
          <PrivateRoute component={Dashboard} path="/dashboard" exact />
        </Switch>
      </BrowserRouter>
    );
  }
}

export default App;

this repo could be helpful for you: public and private hoc

CodePudding user response:

You need to create a privateRoute component, you can check this one

<Route
  {...rest}
  render={({ location }) => {
    return loggedUser !== "" ? (
      children
    ) : (
      <Redirect to={{ pathname: "/login", state: { from: location } }} />
    );
  }}
/>

so any component wrapped in privateRoute component will have to go through it and check if the userLogged is empty or not, in your case you will change it to fit your API call.

then on your app.js you will need to wrap them up using privateRoute

<Router>
    <Switch>
      <Route exact path="/login">
        <Login />
      </Route>

      <PrivateRoute exact path="/">
        <Home />
      </PrivateRoute>

      <PrivateRoute exact path="/counter">
        <counter/>
      </PrivateRoute>

      <PrivateRoute exact path="/fetch-data">
        <FetchData/>
      </PrivateRoute>

      <PrivateRoute exact path="/dashboard">
        <Dashboard/>
      </PrivateRoute>

      <PrivateRoute exact path="/settings">
        <Settings/>
      </PrivateRoute>

      <PrivateRoute path="">
        <NotFound />
      </PrivateRoute>
    </Switch>
</Router>

Now all those components in the PrivateRoute, will redirect to the Login page unless the condition inside the PrivateRoute is fulfilled.

  • Related