When my app mounts, i try to fetch the user by token, that is stored in the local storage. If the token is valid, i then set the user from response to the store. I want for user to see /profile page, only when the user is in the store. But i don't seem to have any idea on how to implement it. If there is no user in the store AND they are on some 'protected' pages like /profile i want to redirect them to login. But the problem is, at the beginning there is no user in the store, so i can't just check for it, and then conditionally redirect(or not) to other pages when the user reloads the page.
App.js:
useEffect(()=> {
dispatch(preserveUser())
}, [dispatch])
User.sagas.js:
export function* handleUserPreserve() {
try {
yield put(resetState());
yield put(setUserLoading(true));
const user = yield call(
getItems,
`query {
getUserByToken {
purchasedProducts
orders
token
_id
email
firstName
}
}`
)
yield put(setUser(user.data.getUserByToken));
yield put(setUserLoading(false));
} catch (error) {
yield put(setUserError(error.message.replace('GraphQL error: ', '')));
yield put(setUserLoading(false));
}
}
export default function* userSaga() {
yield takeEvery(PRESERVE_USER, handleUserPreserve);
}
Initial state:
export const initialState = {
userData: null,
};
You should add another field in state, like isUserLoaded: false
.
As soon as you receive response from api, mark it as true. Then use both user
and isUserLoaded
in your condition for redirection.
If you are using HOC for protected route, then you can modify the conditions to something like below to make it work in your case.
function ProtectedRoute ({component: Component, authed, ...rest}) {
return (
<Route
{...rest}
render={(props) => isUserLoaded === true && !user
? <Redirect to="/login" />
: <Component {...props} /> }
/>
)
}
You can optimize it to your needs but surely you need another variable which will indicate that api has returned a response, and then you can check if the user exist in store or not.