如何在React组件外获取history实例实现无刷新路由跳转
可行实现方案
你之前出现useLocation返回值或者withRouter传入的location属性为undefined的问题,是因为react-router v6的BrowserRouter内部默认自建独立的history实例,和你外部导出的实例不共享状态导致的,按照以下步骤操作即可解决:
1. 创建全局共享history实例
新建src/utils/history.ts文件,代码如下:
import { createBrowserHistory } from 'history'; // 如果是hash路由,替换为createHashHistory export const history = createBrowserHistory();
如果项目未安装history依赖,执行npm install history或者yarn add history安装即可。
2. 替换根路由的BrowserRouter
找到项目入口的路由配置文件,将原本的BrowserRouter替换为react-router-dom导出的原生Router组件,并传入我们创建的全局history实例:
import { Router } from 'react-router-dom'; import { history } from '@/utils/history'; // 根组件示例 function RootApp() { return ( <Router history={history}> {/* 原有路由、页面内容全部保留不变 */} </Router> ); }
3. 在服务文件中引入history使用
修改AuthService.ts代码
import { history } from '@/utils/history'; logout() { if (!isEmpty(localStorage.getItem("authToken"))) { remove("user/logout").then(() => { if (history.location.pathname !== "/auth/login") { localStorage.removeItem("authToken"); // 无刷新跳转 history.push("/auth/login"); } }); } }
修改ApiService.ts代码
import { history } from '@/utils/history'; import { AxiosError } from 'axios'; const handleError = (err: AxiosError) => { if ( err.response?.status === 401 && history.location.pathname !== "/auth/login" ) { history.push("/auth/login"); } captureException(err); return { message: (err.response && err.response.data.message) || err.toString().split(":")[1] || "Something Went Wrong", }; };
注意事项
- 项目中原有的
useNavigate、useLocation等react-router hooks可以正常使用,不受影响 - 所有跳转操作统一使用
history.push(保留历史记录)或者history.replace(替换当前历史记录),不要直接修改history.location属性 - 如果使用的是hash路由模式,仅需将创建实例的方法从
createBrowserHistory改为createHashHistory即可
内容的提问来源于stack exchange,提问作者pradeep kumar
相关产品推荐
相关产品推荐

