Darshan
Darshan

Reputation: 21

Private Route with Redux

I am trying to create a private route which checks user authentication. But the Private route renders before data from redux Is updated. The component has like isauthenticated variable which eventually updates to true but the component renders first before it gets updated. As the redux has its value as false at 1st render.

import React, { Component } from 'react'
import {connect} from 'react-redux'
import {Route, Redirect } from 'react-router-dom'

const PrivateRoute = ({component: Component, isAuthenticated, ...rest}) =>{
    return(
        <Route {...rest} render={
            (props) => {
                if(isAuthenticated) { 
                    return <Component {...props}/>
                }else{
                    return <Redirect to="/login"/>
                }

            }
        }/>
    )
}

const mapStateToProps = state =>{
    return{
        isAuthenticated: state.token !== null
    }
}

export default connect(mapStateToProps, null)(PrivateRoute)

Upvotes: 1

Views: 778

Answers (2)

Miad Vosoughi Nia
Miad Vosoughi Nia

Reputation: 1

Simply, you can add this option:

{ pure: false }

to connect and you should be good to go.

export default connect(mapStateToProps, null, null, {
  pure: false,
})(PrivateRoute);

Upvotes: 0

Makan
Makan

Reputation: 699

You can wrap your router inside an auth-is-loaded component:

import React from "react";
import { useSelector } from "react-redux";
import { isLoaded } from "react-redux-firebase";

export default function AuthIsLoaded({ children }) {
  const auth = useSelector(state => state.firebase.auth);

  if (isLoaded(auth)) return children;
  return <div>Loading...</div>;
}

So App.js will be like this:

  return (
    <Provider store={store}>
        <BrowserRouter>
          <AuthIsLoaded>
            <NavBar />
              <Switch>
                <Route exact path="/" component={Home} />
                <PrivateRoute path="/about" component={About} />
                <PrivateRoute path="/profile" component={Profile} />
                <Route path="/login" component={Login} />
                <Route path="/signup" component={SignUp} />
                <Route path="/logout" component={Logout} />
              </Switch>
            </AuthIsLoaded>
        </BrowserRouter>
    </Provider>
  );

So after auth loaded your switch will be rendered PrivateRoutes wont get isAuthenticated before redux load it.

Sorry about some extra code, I copied from my app, but you should get the idea.

Upvotes: 1

Related Questions