React项目中Logout组件执行登出逻辑前先跳转问题如何解决
问题解决方法
问题根因
当前Logout组件的重定向逻辑和异步登出逻辑是并行执行的:组件挂载后立刻触发return <Redirect />跳转,不会等待useEffect中的后端登出请求、store状态清除操作执行完成,才会出现路由校验误判、两次跳转的体验问题。
修复方案
方案1:修改Logout组件,增加跳转等待逻辑
给Logout组件增加状态控制重定向时机,等待登出逻辑完全执行完成后再触发跳转,同时可以增加加载提示避免用户误以为页面卡顿。
修改后的完整代码如下:
import React, { useEffect, useState } from 'react'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { Redirect, Switch } from 'react-router-dom'; import * as auth from './redux/AuthRedux'; import { logout } from './redux/AuthCRUD'; import { RootState } from '../../../setup'; export function Logout() { const accessToken: string = useSelector<RootState>(({ auth }) => auth.accessToken, shallowEqual) as string; const dispatch = useDispatch(); // 新增状态:标记登出逻辑是否执行完成 const [logoutCompleted, setLogoutCompleted] = useState(false); useEffect(() => { logout(accessToken) .then((response) => { dispatch(auth.actions.logout()); }) .catch((err) => { // 接口异常兜底:无论后端是否返回成功,都清空本地登录态避免用户无法登出 dispatch(auth.actions.logout()); console.error('登出请求异常', err); }) .finally(() => { // 无论请求成功失败,都标记完成触发跳转 setLogoutCompleted(true); }); }, [dispatch, accessToken]); // 登出完成前展示加载态,完成后再跳转 if (logoutCompleted) { return ( <Switch> <Redirect to='/auth/login' /> </Switch> ); } return <div className="logout-loading">正在登出,请稍候...</div>; }
方案2:移除Logout路由组件,直接在登出按钮处处理逻辑(更简洁)
不需要单独配置/logout路由,直接给登出按钮绑定点击事件,异步逻辑执行完成后手动跳转登录页,减少冗余路由组件:
// 如果你用react-router v5 import { useHistory } from 'react-router-dom'; // 如果你用react-router v6 // import { useNavigate } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import * as auth from './redux/AuthRedux'; import { logout } from './redux/AuthCRUD'; // 组件内逻辑 const history = useHistory(); // v6写法:const navigate = useNavigate(); const dispatch = useDispatch(); const accessToken = useSelector(({ auth }) => auth.accessToken); const handleLogout = () => { logout(accessToken) .then(() => dispatch(auth.actions.logout())) .catch(() => dispatch(auth.actions.logout())) .finally(() => { history.push('/auth/login'); // v6写法:navigate('/auth/login'); }); }; // 按钮渲染 <button onClick={handleLogout} className='menu-link px-5'> Sign Out </button>
这种方案省去了路由跳转的中间步骤,也不会出现路由校验误判的问题,实现更简单。
内容的提问来源于stack exchange,提问作者Uroš Milosavljević
相关产品推荐
相关产品推荐

