1
votes

This is my initial state in authReducer.

const initialState = {
    token:'',
    isLogin:  false,
    error: {}
};
function AuthReducer(state = initialState, action) {
    switch(action.type){
        case AUTH_SUCCESS:
            return sessionStorage.setItem('token',action.payload),{
                ...state,
                isLogin: true,
                token: action.payload,
                error: {}
            };
        case AUTH_FAILED:
            return {
                ...state,
                isLogin: false,
                token: '',
                error: action.payload
            };
            default:
            return state
    }
}
export default AuthReducer;

This is my login component that works fine. User can authenticate and everything is working fine:

class Login extends Component {
    constructor(props){
        super(props);
        this.state ={
            username: '',
            password: ''
        }
    }
    onSubmit = e => {
        e.preventDefault();

        this.props.login(this.state.username, this.state.password);
    }
    
    render() {
       .....
        )
    }
}

const mapStateToProps = state => {
    return {
        get: { auth : state.AuthReducer}
    }
}
const mapDispatchToProps = dispatch => {
    return {
        login: (username, password) => {
            return dispatch(login(username, password));
        }
    };
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Login));

And my router is something like this:

class App extends Component {
  constructor(props){
    super(props)
  }
  render() {
    let PrivateRoute = ({ component: ChildComponent, isLogin, ...rest}) => {
      console.log({...rest}, "this is rest")
      return <Route 
      {...rest}
        render={props => {
          if (!isLogin) {
            return <Redirect to="/login" />;
        } else {
          return <ChildComponent {...props} />
        }
      }} />
    }
    return (
      <div>
          <Home />
          <Switch>
          <PrivateRoute path="/" exact isLogin={this.props.auth.isLogin}  component={mainContent} />
          <PrivateRoute path="/posts" isLogin={this.props.auth.isLogin} component={Posts} />
          <Route path="/login"  component={Login} />
        </Switch>
      </div>
    );
  }
}
const mapStateToProps = state => {
  return {
    auth: state.AuthReducer
  }
}
const mapDispatchToProps = dispatch => {
  return {
    getUser: () => {
      return dispatch(getUser());
    }
  };
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));

In react-router, they said you must use withRouter from react-router-dom. my problem is login works fine. but I don't have access to my props in my privateroute so when react renders a new page my isLogin sets to false. I have some idea that router doesn't know about my redux or protected components cant are not aware of changes in props.all of my child components in my PrivateRoute are connected with react-redux.

1

1 Answers

0
votes

Here the issue is you are not getting isLogin value from reducer. When you try to get reducer value in your router file:

const mapStateToProps = state => {
  return {
    auth: state.AuthReducer
  }
}

You will get this.props.auth.AuthReducer as undefined as the state value in mapStateToProps will be your initial value from your reducer. So, either you can get Login from state directly like below and try to access this.props.auth:

const mapStateToProps = state => {
  return {
    auth: state.isLogin
  };
};

or you can replace you code with this and use this.props.auth.isLogin:

const mapStateToProps = state => {
  return {
    auth: state
  };
};

Refer this for more: https://codesandbox.io/s/react-router-dom-with-private-route-sr61v