I am trying to use history.push()
after setting the token. Somehow the page doesn't redirect to a new path. I have used useHistory
feature for accessing history. Once I reload the page it is redirecting to home. I tried other sort of hacks but unable to find solution. Please help.
App.js
function App() {
const [isAuthenticated, setAuthenticated] = useState(false);
useEffect(()=>{
if(cookie.get('authorization')){
setAuthenticated(true);
}
else{
setAuthenticated(false);
}
},[])
return (
<Router>
<Switch>
<Route exact path="/">
{isAuthenticated?<Redirect to="/home"/>:<Login />}
</Route>
<PrivateRoute exact path="/user/:id" component={UserDetail} auth={isAuthenticated} />
<PrivateRoute exact path="/createuser" component={CreateUser} auth={isAuthenticated} />
<PrivateRoute exact path="/home" component={ListUser} auth={isAuthenticated} />
</Switch>
</Router>
);
}
export default App;
login.js
import React, { useEffect, useState } from 'react';
import {useHistory} from 'react-router-dom';
function Login() {
const history = useHistory();
const loginUser = (body) => {
SetLoader(true);
fetch('/api/v2/users/tokens', {
method: 'POST',
body: JSON.stringify(body),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
SetLoader(false);
if (response.status == 200) {
SetError(false);
cookie.set('authorization',response.headers.map.authorization,{path:'/'});
history.push('/');
}
else {
SetError(true);
StoreResponse(JSON.parse(response._bodyInit).message);
}
})
.catch((error) => {
console.error('Error:', error);
});
}
}
export default Login;
I don't see where history
is defined in Login
component. Also, you set the cookie, but isAuthenticated
is only ever set when App
component mounts, it is never updated later.
You could pass a callback to Login
to update the state in App
and let the redirect happen naturally when App
rerenders and rerenders the routes with the re-enclosed isAuthenticated
state. The Switch
also already attempts to match and render routes exclusively, so order your paths most specific to least specific and you won't need to add the exact
prop to every route.
App
function App() {
const [isAuthenticated, setAuthenticated] = useState(false);
useEffect(() => {
if (cookie.get("authorization")) {
setAuthenticated(true);
} else {
setAuthenticated(false);
}
}, []);
return (
<Router>
<Switch>
<PrivateRoute
path="/user/:id"
component={UserDetail}
auth={isAuthenticated}
/>
<PrivateRoute
path="/createuser"
component={CreateUser}
auth={isAuthenticated}
/>
<PrivateRoute
path="/home"
component={ListUser}
auth={isAuthenticated}
/>
<Route path="/">
{isAuthenticated ? (
<Redirect to="/home" />
) : (
<Login setAuthenticated={setAuthenticated} /> // <-- pass callback
)}
</Route>
</Switch>
</Router>
);
}
Login
function Login({ setAuthenticated }) { // <-- destructure prop
const loginUser = (body) => {
SetLoader(true);
fetch("/api/v2/users/tokens", {
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json"
}
})
.then((response) => {
if (response.status == 200) {
SetError(false);
cookie.set("authorization", response.headers.map.authorization, {
path: "/"
});
setAuthenticated(true); // <-- set authenticated
} else {
SetError(true);
StoreResponse(JSON.parse(response._bodyInit).message);
}
})
.catch((error) => {
console.error("Error:", error);
})
.finally(() => {
SetLoader(false); // <-- set loading false in finally block
});
};
...
}