我为了两个目的使用了两个路由守卫,但在一个特殊的情况下,他们不能正常工作,我认为他们处于竞争状态.
路由
<Router>
<Routes>
<Route element={<GlobalGuard />}>
<Route path="/login" element={<Login />} />
<Route element={<LocalGuard />}>
<Route path="/projects/*" element={<Projects />}>
...
</Route>
</Route>
</Routes>
</Router>
全球卫士
const dispatch = useDispatch();
const [loading, setLoading] = useState(true);
const [validUser, setValidUser] = useState(false);
const location = useLocation();
useEffect(() => {
(async () => {
try {
if (localStorage.getItem('token')) {
const localUser = JSON.parse(localStorage.getItem('user'));
if (localUser && localUser.hasOwnProperty('email')) {
const pingStatus = await pingUser({ email: localUser.email });
if (pingStatus == 200) {
dispatch(fillUser(JSON.parse(localStorage.getItem('user');
setValidUser(() => true);
setLoading(() => false);
} else {
localStorage.removeItem('user');
localStorage.removeItem('token');
setValidUser(() => false);
setLoading(() => false);
}
} else {
localStorage.removeItem('user');
localStorage.removeItem('token');
setValidUser(() => false);
setLoading(() => false);
}
} else {
localStorage.removeItem('user');
setValidUser(() => false);
setLoading(() => false);
}
} catch (err) {
setValidUser(() => false);
setLoading(() => false);
}
})();
}, [location.pathname]);
console.log(location.pathname); // for checking if render correct
return loading ? <ServerLoad /> : <Outlet context={validUser} />;
地方警卫队
const hasValidJwt = useOutletContext();
console.log(hasValidJwt);
return hasValidJwt ? <Outlet /> : <Navigate to="/login" />;
登录.jsx
const navigate = useNavigate();
const onSubmit = async (data) => {
try {
const res = await loginUser(data);
dispatch(setUser(res));
localStorage.setItem('token', res.token);
localStorage.setItem('user', JSON.stringify(res.user));
navigate('/projects');
}
...
};
当onSubmit代码在登录页面中运行时,在理想情况下,全局防护的useEffect应该使hasValidUser为True,并使页面导航到项目,但实际上它只会刷新.
经过几天的调试,我发现全局警卫的useEffect的控制台.日志(log)在本地警卫的控制台之后运行,它记录false
,所以它再次导航到login
.即使在hasValidUser设置为true
之后,页面在登录时仍会缩水.
有没有人能谈谈他们的观点.
In Short个
当我第一次单击LOGIN时,它只用适当的值填充本地存储,第二次它实际上转到/Projects