Skip to content

Instantly share code, notes, and snippets.

@rcanepa
Last active March 2, 2023 08:29
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save rcanepa/b4ce0dff8d85b357504e04b03e69ac66 to your computer and use it in GitHub Desktop.
Save rcanepa/b4ce0dff8d85b357504e04b03e69ac66 to your computer and use it in GitHub Desktop.
Private routes with React Router v4
function PrivateRoute ({component: Component, authenticated, ...rest}) {
return (
<Route
{...rest}
render={(props) => authenticated === true
? <Component {...props} />
: <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
/>
)
}
<Route path='/' exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRoute authenticated={this.state.authenticated} path='/invoices' component={Invoices} />
@mcshiz
Copy link

mcshiz commented Jan 7, 2018

If you also want to pass your own props to the private component change line 6 to this
<Component {...rest} {...props} />
So you can do something like this
<PrivateRoute authenticated={this.state.authenticated} path='/invoices' component={Invoices} user={this.state.user}/>
or in the case of redux
<PrivateRoute authenticated={this.state.authenticated} path='/invoices' component={Invoices} user={this.props.user}/>

It's important to note the order of which the destructured props are being passed to the component. {...rest} contains the React Router props when the initial component is rendered so the match and location properties will be '/' and they will overwrite the {...props} properties which contains the updated react router information.

@thiagocoelho
Copy link

thiagocoelho commented Jan 11, 2018

How can I nest private routes? I was trying something like:

const PrivateRoute = ({component: Component, ...rest}) => (
	<Route {...rest} render={props => (
		app.isAuthenticated ? (
			<Component {...props}>
				{props.children}
			</Component>
		) : (
			<Redirect to={{
				pathname: '/',
				state: { from: props.location }
			}}/>
		)
	)}/>
);
<PrivateRoute path='/dashboard' component={Dashboard}>
	<Route path='/tabulacao' component={Disposition} />
</PrivateRoute>

@estebanmainieri
Copy link

What about this one?

const {
  authenticated,
} = this.state

const public = (
  <Switch>
    <Route exact path='/' component={Home} />
  </Switch>

const private = (
  <Switch>
    <Route exact path='/invoices' component={Invoices} />
  </Switch>
)

return (authenticated) ? private : public

@bradtraversy
Copy link

bradtraversy commented Mar 19, 2018

Using Redux if anyone needs it..

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

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

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

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

export default connect(mapStateToProps)(PrivateRoute);

@kanlanc
Copy link

kanlanc commented Jun 11, 2018

Hey guys, this question might sound weird but I am really very confused with this, so bear with me.

In the below code,

function PrivateRoute ({component: Component(-------Here we are using "C" but when we are passing the prop we are using "c" and if memory serves when destructuring the right side of the : gets its value assigned to the left side of the colon in the object and also in the bottom when we are typing the component we are also using "C" how and why is this working????---------- ) , authenticated, ...rest}) {
return (
<Route
{...rest}
render={(props) => authenticated === true
? <Component {...props} />(-------------Here we are using again "C"----------------------)
: <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
/>
)
}

<Route path='/' exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRoute authenticated={this.state.authenticated} path='/invoices' component={Invoices} />  (-------------Here we are using again "c"----------------------)

Are my concepts wrong or is there some magic at play?

@hansfpc
Copy link

hansfpc commented Jul 18, 2018

yarn add react-private-route

@jermsam
Copy link

jermsam commented Jul 30, 2018

hello, what's the proper way to authenticate a route in react-router-dom? With this snippet I get two errors that I do not get how to solve:

Can't call setState (or forceUpdate) on an unmounted component.
looks like the authUser state gets set after the checkNotNull(obj) function is run.
Kindly help me with any of these. Thank you.
https://gist.github.com/jermsam/88c6dcc04f7db3dd323a668215a797d8

@jermsam
Copy link

jermsam commented Jul 30, 2018

The error persists even when I use the react-private-route module recommended by @hansfpc

@krigulson
Copy link

Using Redux if anyone needs it..

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

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

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

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

export default connect(mapStateToProps)(PrivateRoute);

nice one @bradtraversy
does the exact thing what i needed. when user is logged in then route is available and when user is on Private route and logs out then user is redirected aswell. Other similar solutions somehow didn't worked for me. But your solution works!

Many thanks!

@tarang9211
Copy link

Can this be implemented via cookies?

@juliettegodyere
Copy link

Hello, I am having some issues with the React Router Dom PrivateRoute. The private route redirects to the login page even when the user is authenticated. I can't figure out the exact thing that I am doing wrong. Please see the routers and the privateRoute code below.

My Route
<Switch>
<Route path="/login" render={(props) => <Login onLogin={this.handleLogin} {...props} />}></Route>
<Route path="/signup" component={Signup}></Route>
<PrivateRoute exact path="/" authenticated={this.state.isAuthenticated} component={Dashboard} handleLogout = {this.handleLogout}></PrivateRoute>
<PrivateRoute exact path="/dashboard" authenticated={this.state.isAuthenticated} component={Dashboard} handleLogout {this.handleLogout}></PrivateRoute>
<PrivateRoute exact path="/members" authenticated={this.state.isAuthenticated} component={MemberList} handleLogout={this.handleLogout}></PrivateRoute>
<PrivateRoute exact path="/members/new" authenticated={this.state.isAuthenticated} component={NewMember} handleLogout={this.handleLogout}></PrivateRoute>
<PrivateRoute exact path="/members/view" authenticated={this.state.isAuthenticated} component={ViewMember} handleLogout={this.handleLogout}></PrivateRoute>
<Route component={NotFound}></Route>
</Switch>

const PrivateRoute = ({ component: Component, authenticated, ...rest }) => (
<Route
{...rest}
render={props =>
authenticated ? (
<Component {...rest} {...props} />
) : (
<Redirect
to={{
pathname: '/login', state: { from: props.location }
}} /> ) } /> );

@adil-waqar
Copy link

Hey guys, this question might sound weird but I am really very confused with this, so bear with me.

In the below code,

function PrivateRoute ({component: Component(-------Here we are using "C" but when we are passing the prop we are using "c" and if memory serves when destructuring the right side of the : gets its value assigned to the left side of the colon in the object and also in the bottom when we are typing the component we are also using "C" how and why is this working????---------- ) , authenticated, ...rest}) {
return (
<Route
{...rest}
render={(props) => authenticated === true
? <Component {...props} />(-------------Here we are using again "C"----------------------)
: <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
/>
)
}

<Route path='/' exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRoute authenticated={this.state.authenticated} path='/invoices' component={Invoices} />  (-------------Here we are using again "c"----------------------)

Are my concepts wrong or is there some magic at play?

I have this same confusing. Can anyone help?

@orenaksakal
Copy link

orenaksakal commented Dec 27, 2020

@adil-waqar
@kanlanc

You can rename while destructuring thats what is happening there like so {actualName: newName},
so we receive component and rename it to be Component after desctucturing with {component: Component}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment