react-router-dom 5.2.0引入useNavigate报错:该成员未从模块中导出
报错核心原因
useNavigate是 react-router-dom v6 版本新增的路由Hook,你当前锁定依赖版本为 react-router-dom 5.2.0,该版本根本没有导出这个方法,因此会直接触发导出不存在的报错。- 即使升级到支持
useNavigate的v6版本,现有代码写法依然违规:React Hooks 只能在函数组件顶层、或者自定义Hook内部调用,你将Hook写在了独立的普通异步导出函数createCheckoutSession内部,本身就不符合React Hooks的调用规则。 - 现有空用户判断的逻辑存在漏洞:判断未登录执行跳转后没有中断后续代码,会直接访问空对象的
user.uid字段,触发空引用报错。
适配当前现有依赖(react-router-dom 5.2.0)的修复方案
不需要升级任何依赖,直接替换成v5体系支持的路由跳转逻辑即可:
- 删除代码中
import {useNavigate} from 'react-router-dom';这行无效引入 - 由于
createCheckoutSession是独立的普通业务函数,不属于被Route包裹的组件,无法直接获取路由内置的跳转能力,有两种实现路径:- 路径1:由调用
createCheckoutSession的组件,把v5注入的history对象作为参数传入函数
修改后的核心代码片段:
调用方的适配写法:export async function createCheckoutSession(activtyStatus, history){ let user = firebase.auth().currentUser; if (user == null) { // v5版本对应的跳转API history.push('/clients') // 跳转逻辑执行后直接中断后续流程,避免空引用 return; } // 原有业务逻辑保持不变 if (activtyStatus == "canceled") { price = 'price_1IfmDsKDPaWWeL1ywjMTGarh' } // ... 后续firestore查询、stripe跳转的逻辑和原有代码保持一致 }// 如果是函数组件,需要先用withRouter高阶组件包裹,才能从props拿到路由注入的history import { withRouter } from 'react-router-dom'; function CheckoutEntry(props) { const handlePay = () => { // 调用函数时把拿到的history作为入参传入 createCheckoutSession('canceled', props.history) } return <button onClick={handlePay}>发起支付</button> } export default withRouter(CheckoutEntry); - 路径2:在项目内创建独立的全局路由实例,所有业务代码都可以直接引入这个实例执行跳转,不需要逐层传参。该方式是react-router-dom v5官方支持的全局跳转实现。
- 路径1:由调用
- 必须补上空判断后的中断逻辑:只要识别到用户未登录执行完跳转,立刻写
return终止后续代码执行,避免空引用。
需要将 react-router-dom 升级到v6及以上兼容版本,同时调整调用规则:
- 不能直接在普通异步函数内部调用
useNavigate,需要在调用方的函数组件内部先拿到navigate实例,再作为参数传入业务异步函数,调用逻辑和上面传history的写法完全一致 - 升级后需要同步调整项目内现有路由定义的API写法,适配v6的路由规则,避免连带出现其他路由报错。
内容的提问来源于stack exchange,提问作者user15576045
相关产品推荐
相关产品推荐

