Reputation: 107
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?
Upvotes: 3
Views: 911
Reputation: 101
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.
Upvotes: 2