Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

348
Views
How to add protected routes in react redux

I have created a login component on which I have all the logic stuff.

The login reducer is:

const openState = {
  loggedIn: null,
  user: null
}

export default (state = openState, action) => {
  switch (action.type) {
    case LOGIN:
      return { ...state, loggedIn: true, user: action.payload }
    case LOGOUT:
      return { ...state, loggedIn: false, user: null }
    default:
      return openState
  }
}

The Action :

export const logIn = (user) => {
  return {
    type: LOGIN,
    payload: user
  }
}

export const logOut = () => {
  return {
    type: LOGOUT
  }
}

everything is working just fine but I'm not sure how to pass the loggedIn and user props from action into the routes component in order to secure all routes:

const MainRoutes = props => {
  const { loggedIn } = props;

  console.log(props.loggedIn)

return (
  <Router history={history}>
    <Baseline />
    <Menu/>
    <Container maxWidth="md">
      <Switch>
        <Route exact path="/Login" component={Login} />
        <Route exact path="/Carousel" component={Carousel} />
        <Route exact path="/Stepper" component={Stepper} />
        <Route component={NotFound} />
      </Switch>
    </Container>
  </Router>
);
}

const mapStateToProps = (state) => {
return { loggedIn: state.loggedIn };
};

export default connect(mapStateToProps)(MainRoutes);

If I'll console.log the loggedIn props I get undefined :| Based on loggedIn I can create a logic into the routes component.

over 4 years ago · Santiago Trujillo
6 answers
Answer question

0

You could simply define a custom ProtectedRoute component that'll be connected to redux state. In your case it should map state.auth.loggedIn and state.auth.user to props and perform a Redirect if those values are falsy:

import React from "react";
import { Route, Redirect } from "react-router-dom";
import PropTypes from "prop-types";


const ProtectedRoute = (props) => {
  const { redirectPath, component, user, loggedIn, ...routeProps} = props;
  const Component = component;
  const isAccessible = Boolean(user) && loggedIn;

  return (
    <Route
      {...routeProps}
      render={props => {
        if (isAccessible) return <Component {...props} />;
        return <Redirect to={{ pathname: redirectPath || "/Login" }} />;
      }}
    />
  );
};

ProtectedRoute.propTypes = {
  path: PropTypes.string.isRequired,
  redirectPath: PropTypes.string,
  component: PropTypes.oneOfType([
    PropTypes.shape({ render: PropTypes.func.isRequired }),
    PropTypes.func
  ]),
};

const mapStateToProps = (state) => {
  return { 
    loggedIn: state.auth.loggedIn, 
    user: state.auth.user 
  };
};

export default connect(mapStateToProps)(ProtectedRoute);

With this in place your MainRoutes won't need connect anymore:

const MainRoutes = props => {
  return (
    <Router history={history}>
      ...
      <Container maxWidth="md">
        <Switch>
          <Route exact path="/Login" component={Login} />
          <ProtectedRoute exact path="/Carousel" component={Carousel} />
          <ProtectedRoute exact path="/Stepper" component={Stepper} />
          <Route component={NotFound} />
        </Switch>
      </Container>
    </Router>
  );
}

export default MainRoutes;

Update:

If you want to keep auth state after page refresh you'll need to perform some extra setup of your redux store. The main idea is to subscribe on every action and put a fresh copy of state into localStorage or cookies and also to persist initialState from selected storage before your app boots up. Here is an example:

function getFromStorage(key) {
  try {
    return JSON.parse(window.localStorage.getItem(key)) || {};
  } catch (err) {
    return {};
  }
}

const initialState = getFromStorage("APP_STATE");

const store = createStore(
  rootReducer,
  initialState, // should go after root reducer
  ...
);

store.subscribe(() => {
  window.localStorage.setItem("APP_STATE", JSON.stringify(store.getState()));
});

And here's the working sandbox (bootstrapped by SuleymanSah)

over 4 years ago · Santiago Trujillo Report

0

What I would do in this scenario is to create a private route basically, which would only be accessible if you are logged in, or in your case, if the loggedIn in your loggedIn: state.loggedIn is true and if a user exists in state.auth.user. And if both are false, it will redirect you to the /login page to login or signup first before accessing those private routes.

So to create a private route or a <PrivateRoute />,

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';


const PrivateRoute = ({ 
  component: Component,
  auth: { user, loggedIn },
  ...rest 
}) => (
  <Route 
    {...rest} 
    render={props => 
      loggedIn && Boolean(user) ? (
        <Component {...props} />  
      ) : (
        <Redirect to="/login" />
      )
    } 
  />
);

PrivateRoute.propTypes = {
  auth: PropTypes.object.isRequired
}

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps)(PrivateRoute);

This will create that private route or <PrivateRoute /> for you which you can import into your MainRoutes file and then you can pass on the components to it which are supposed to be protected by the private route.

const MainRoutes = props => {
  return (
    <Router history={history}>
      <Baseline />
      <Menu/>
      <Container maxWidth="md">
        <Switch>
          <Route exact path="/Login" component={Login} />
          <PrivateRoute exact path="/Carousel" component={Carousel} />
          <PrivateRoute exact path="/Stepper" component={Stepper} />
          <Route component={NotFound} />
        </Switch>
      </Container>
    </Router>
  );
}

export default MainRoutes;

This way the components to be protected will check if the user exists and if you are logged in or not and if true, it will let you access those components.

over 4 years ago · Santiago Trujillo Report

0

The below code worked for me.

const SecretRouter = ({ component: Component, location, loggedIn , ...rest }) => (
  <Route
    location={location}
    {...rest}
    render={(props) =>
      loggedIn === true ? (
        <Component {...props} />
      ) : (
          <Redirect
            to={{
              pathname: "/Login"
            }}
          />
      )
    }
  />
);

const mapStateToProps = (state) => {
return { loggedIn: state.loggedIn };
};

export const PrivateRouter = connect(mapStateToProps)(
  SecretRouter
);

const MainRoutes = props => {

return (
  <Router history={history}>
    <Baseline />
    <Menu/>
    <Container maxWidth="md">
      <Switch>
        <Route exact path="/Login" component={Login} />
        <PrivateRouter exact path="/Carousel" component={Carousel} />
        <PrivateRouter exact path="/Stepper" component={Stepper} />
        <Route component={NotFound} />
      </Switch>
    </Container>
  </Router>
);
}


export default MainRoutes;
over 4 years ago · Santiago Trujillo Report

0

As others already described, you had better to create a Protected Route to accomplish what you want. You simply redirect the user to the Login route if he/she is not logged in.

Here is my implementation: (codesandbox)

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";

const ProtectedRoute = ({
  path,
  component: Component,
  render,
  loggedIn,
  ...rest
}) => {
  return (
    <Route
      path={path}
      {...rest}
      render={(props) => {
        if (loggedIn) {
          return Component ? <Component {...props} /> : render(props);
        }
        return (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: props.location }
            }}
          />
        );
      }}
    />
  );
};

const mapStateToProps = (state) => {
  const { loggedIn } = state.auth;
  return {
    loggedIn
  };
};

export default connect(mapStateToProps)(ProtectedRoute);
over 4 years ago · Santiago Trujillo Report

0

You can create a Guard which gets login status from Redux store and renders children if it is logged in, otherwise redirect to somewhere else. To get the state from the store, you can use useSelector React Hook.

import { useSelector } from 'react-redux';

function AuthGuard({children}) {
    const loggedIn = useSelector(store => store.loggedIn);
    
    if (loggedIn) {
        return children;  
    } else {
        return <Redirect to="/login" />
    }
}

and in the route

    <Container maxWidth="md">
      <Switch>
        <Route exact path="/Login" component={Login} />
        <AuthGuard>
            <Route exact path="/Carousel" component={Carousel} />
            <Route exact path="/Stepper" component={Stepper} />
        </AuthGuard>
        <Route component={NotFound} />
      </Switch>
    </Container>
over 4 years ago · Santiago Trujillo Report

0

This approach uses the official example of react router, basically you need to connect your redux store with this ProtectedRoute component

import { connect } from "react-redux";
import { Route, Redirect } from "react-router-dom";

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

const mapStateToProps = (state) => {
  return { loggedIn: state.auth.loggedIn };
};

export default connect(mapStateToProps)(PrivateRoute);

As you can see you're passing the loggedIn value to this new route component, so it this is false it will return you to the login page.

In order to use it just call the component in your router:

import PrivateRoute from "./PrivateRoute";

const MainRoutes = () => {

return (
  <Router history={history}>
    <Baseline />
    <Menu/>
    <Container maxWidth="md">
      <Switch>
        <Route exact path="/Login" component={Login} />
        <PrivateRoute exact path="/Carousel" component={Carousel} />
        <PrivateRoute exact path="/Stepper" component={Stepper} />
        <Route component={NotFound} />
      </Switch>
    </Container>
  </Router>
);
}

It is a nice approach because you're not connecting the MainRoutes component to the store, which in my opinion is not something you would need in that component, you'll end up using it in the components inside the Routes.

Also you forgot to add the state.auth.loggedIn to your Main Routes mapStateToProps, that's why is undefined when you're trying to use it.

Here's a small sandbox that I did to illustrate the process: https://codesandbox.io/s/unruffled-keller-pwlib

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!