I'm implementing authentication into my app, the issue I am having is on refresh the state is not persistent so I get redirected back to the login screen. How can I use React Hooks to check if there is an authToken in local storage
to keep me logged in on refresh.
This is My Protected Route That checks for auth tokens
<Route
{...rest}
render={
props=>
authTokens ? (
<Component {...props}/>
) : (
<Redirect
to ={
{
pathname: '/login',
state: {
from: props.location
}
}
}
/>
This is my Login page Function
function Login(props) {
const [isLoggedIn, setLoggedIn] = useState(false);
const [isError, setIsError] = useState(false);
const [firstName, setUserName] = useState("");
const [password, setPassword] = useState("");
const { setAuthTokens } = useAuth();
function postLogin() {
axios.post("http://10.6.254.22:5000/userinformation/login", {
firstName,
password
}).then(result => {
if (result.status === 200) {
console.log('You have been logged in as user: ' +result.data[0].firstName)
setAuthTokens(result.data);
setLoggedIn(true);
} else {
setIsError(true);
}
}).catch(e => {
setIsError(true);
});
}
if (isLoggedIn) {
return <Redirect to="/" />;
}
Below is my Hook that contains the state
const [authTokens, setAuthTokens] = useState();
const setTokens = (data) => {
localStorage.setItem("authTokens", JSON.stringify(data));
setAuthTokens(data);
}
useEffect(()=> {
let jsonToken = localStorage.getItem('authTokens', JSON.stringify(authTokens))
console.log('JSON TOKEN -----' + jsonToken)
setAuthTokens(jsonToken)
})
How can i set the state authTokens with the local storage
variable on load so that when I refresh the state isnt empty so i dont get logged out on page reload. Also to mention The context provider is set up as so:
<AuthContext.Provider value={{ authTokens, setAuthTokens: setTokens}}>
<ProtectedRoute path="/" exact component={ProfileBox}/>
</AuthContext.Provider>
The problem is that authTokens
is undefined
when your component mounts, so the logic of your Protected route is evaluating to the Redirect
portion of your code, causing the redirection to /login
.
React will remove componentWillMount
hook, so, the solution I found to this specific problem, is to check also for the token in the localStorage
, instead of just checking for the state authTokens
.
This way, your code will be able to evaluate that you have the token (even before the first component update).
The code of your Protected Route
may look like this:
<Route
{...rest}
render={
props=>
(authTokens || localStorage.getItem("authTokens")) ? (
<Component {...props}/>
) : (
<Redirect
to ={
{
pathname: '/login',
state: {
from: props.location
}
}
}
/>
Other possible solutions are:
But I think that if you just want to protect private routes, this solution is sufficient