react-router-dom v6点击导航栏Link链接报错无法跳转组件问题
问题现象
使用版本号为^6.3.0的react-router-dom通过导航栏实现组件路由关联时出现异常:刷新页面对应路由的组件可正常展示,但点击导航栏内的链接无法加载对应组件,点击链接时抛出如下错误:
Uncaught Error: Syntax error, unrecognized expression: /about at oe.error (jquery.min.js:2:12961) at oe.tokenize (jquery.min.js:2:18943) at oe.select (jquery.min.js:2:21833) at Function.oe [as find] (jquery.min.js:2:6808) at w.fn.init.find (jquery.min.js:2:24400) at new w.fn.init (jquery.min.js:2:24889) at w (jquery.min.js:2:896) at HTMLAnchorElement.<anonymous> (custom.js:22:24) at HTMLAnchorElement.dispatch (jquery.min.js:2:41772) at y.handle (jquery.min.js:2:39791)
项目相关代码
index.js
import { BrowserRouter as Router} from 'react-router-dom'; ... const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Router> <App /> </Router> );
App.js
import {Routes , Route} from 'react-router-dom' ... function App() { return ( <> <Navbar /> <Routes> <Route path="/" element = {<Hero />}></Route> <Route path="/about" element = {<About />}></Route> </Routes> </> ); }
Navbar.js
import { Link } from 'react-router-dom' ... <ul className="navbar-nav ml-lg-auto"> <li className="nav-item"> <a href="#home" className="nav-link smoothScroll">Home</a> </li> <li className="nav-item"> <Link to="/about" className="nav-link smoothScroll">About Us</Link> </li> <ul>
问题原因
报错栈明确指向自定义脚本custom.js第22行绑定的锚点点击事件,本质是jQuery平滑滚动逻辑和React Router的Link组件冲突:
你给路由跳转用的Link组件加了smoothScroll类,页面引入的jQuery脚本会给所有带该类名的a标签绑定点击事件,尝试读取a标签的href属性作为jQuery选择器查找DOM元素,实现页内锚点平滑滚动。但路由链接的href值为/about,并非页内锚点格式#xxx,jQuery无法将其识别为合法选择器直接抛出语法错误,同时中断了React Router Link组件的默认路由跳转逻辑,导致点击后无法加载对应组件。
刷新页面能正常展示组件,是因为刷新行为是浏览器直接发起对应路径的请求,本地开发/部署服务端配置了路径重定向到入口index.html后,React Router初始化时会直接匹配当前地址栏路径渲染对应组件,不会触发导航栏的点击事件逻辑,因此表现正常。
修复方案
二选一即可:
- 移除路由Link上的
smoothScroll类名,该类仅保留给页内锚点跳转的原生a标签(比如跳转到#home的首页链接)使用,避免jQuery给路由链接绑定平滑滚动事件。 - 修改
custom.js中的平滑滚动绑定逻辑,仅对href以#开头的.smoothScroll元素绑定事件,过滤掉路由跳转链接,例如在事件逻辑开头增加判断:if (!this.hash.startsWith('#')) return,不要将路由路径传入jQuery选择器查找逻辑。
路由组件放置规则
三个核心路由组件的放置有明确的层级要求:
BrowserRouter:是所有路由相关能力的上下文提供者,所有用到路由API(Link、Routes、Route、路由hooks等)的组件,必须放在BrowserRouter的内部子树中,通常放在项目入口文件最外层包裹整个App根组件,你当前index.js中的写法符合要求。Routes:是路由匹配渲染的容器,内部仅可嵌套Route组件,负责在地址栏路径变化时匹配对应path的Route,渲染对应的element元素。只要放在BrowserRouter内部即可,可放置在任意组件层级,通常和导航栏、页脚这类全局固定布局组件平级,放在页面内容渲染区,你当前App.js中的写法符合要求。Link:是声明式路由跳转组件,最终会渲染为原生a标签,负责实现无刷新路由跳转。只要放在BrowserRouter内部即可放置在任意位置,注意不要给Link绑定会拦截点击事件、打断React Router默认跳转逻辑的自定义事件(本次问题中的jQuery平滑滚动事件就属于这类冲突逻辑)。
内容的提问来源于stack exchange,提问作者Rahul Mallick
相关产品推荐
相关产品推荐

