简体   繁体   中英

Protected React route redirects before props receive Redux state

When I refresh the page, my protected route made with react-router-dom is rendered before mapStateToProps fires and the component receives props. This causes redirection to /login route, although I'm already logged in.

I have a Redux store looking like this:

const initialState = {
    isAuthenticated: false,
    user: {}
};

and a component named App.js which contains routes:

componentDidMount() {
    if (localStorage.token)
        setAuthToken(localStorage.token);

    store.dispatch(loadUser());
}

Where setAuthToken method is adding headers to axios requests. There's also loadUser() method which is an action creator with such code:

export const loadUser = () => async dispatch => {
    if (localStorage.token) {
        setAuthToken(localStorage.token);
    }

    try {
        const res = await axios.get('/api/v1/user');

        dispatch({
            type: USER_LOADED,
            payload: res.data
        });
    }

    catch (e) {
        console.log(e);
    }
};

So it basically changes a store's isAuthenticated field to true and adds user's info into the user object in the store, if there is a JWT token in the localStorage.

In my protected route component I have code that redirects to /login , if Redux store has isAuthenticated equal to false.

render() {
    if (this.props.auth.isAuthenticated === false)
        return (<Redirect to={'/sign-in'}/>);

Now, everything works fine if I click a link to a protected route from the navbar. If I'm logged in, then the protected route shows. If I'm not, then I'm redirected to the /login .

The problem occurs when I refresh the page being on the protected route. I'm immediately redirected to /login , because the page is rendered before the component receives Redux store's state in props.

How can I fix this? Should I somehow wait for the props, or rather change the method of routes protecting?

Well one easy way to fix this would be to add a loading state to your reducer. Add a simple action that is dispatched at the beginning of loadUser that turns loading to true and after the API call when your reducer hits the USER_LOADED case it turns loading to false, fills the user state, changes isAuthenticated to true/false depending if the user is logged in. And change the condition on your protected route component to this.props.auth.isAuthenticated === false && !this.props.user.loading.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM