Next.js项目使用react-router-dom的Link报Router外部使用错误如何解决
问题原因
- 核心错误:你从
react-router-dom导入了<Link>组件使用,但所有react-router-dom的路由组件都必须在<Router>上下文下运行,你导入了BrowserRouter as Router但全程没有使用该组件包裹子节点,导致Link找不到路由上下文抛出报错。 - 次要问题:你在
Navbar.js中存在命名冲突,同时从react-router-dom导入BrowserRouter as Router、从next/router导入Router,重名导入会互相覆盖失效。 - 额外说明:Next.js本身自带基于
pages目录的内置路由能力,不需要额外引入react-router-dom做路由管理,强行混用会导致服务端渲染阶段出现更多兼容问题。
解决方案
方案1:优先推荐,改用Next.js内置路由(无需react-router-dom)
步骤1:卸载冗余依赖
yarn remove react-router-dom # 或使用npm npm uninstall react-router-dom
步骤2:修改Navbar.js代码
替换react-router-dom的路由能力为Next.js原生API:
import { FaBars } from 'react-icons/fa'; import Link from 'next/link'; import { useRouter } from 'next/router'; import styled from 'styled-components'; export const Nav = styled.nav` background: #000; height: 80px; display: flex; justify-content: space-between; padding: 0.5rem calc((100vw - 1000px) / 2); z-index: 10; `; // 封装带激活状态的导航链接 const NavLinkWrapper = ({ href, children, activeStyle }) => { const router = useRouter(); const isActive = router.pathname === href; return ( <Link href={href} passHref> <a className={isActive ? 'active' : ''} style={isActive && activeStyle ? activeStyle : {}}> {children} </a> </Link> ) } export const NavLink = styled(NavLinkWrapper)` color: #fff; display: flex; align-items: center; text-decoration: none; padding: 0 1rem; height: 100%; cursor: pointer; &.active { color: #15cdfc; } `; export const Bars = styled(FaBars)` display: none; color: #fff; @media screen and (max-width: 768px) { display: block; position: absolute; top: 0; right: 0; transform: translate(-100%, 75%); font-size: 1.8rem; cursor: pointer; } `; export const NavMenu = styled.div` display: flex; align-items: center; margin-right: -24px; @media screen and (max-width: 768px) { display: none; } `; export const NavBtn = styled.nav` display: flex; align-items: center; margin-right: 24px; @media screen and (max-width: 768px) { display: none; } `; // 封装按钮链接 const NavBtnLinkWrapper = ({ href, children }) => { return ( <Link href={href} passHref> <a>{children}</a> </Link> ) } export const NavBtnLink = styled(NavBtnLinkWrapper)` border-radius: 4px; background: #256ce1; padding: 10px 22px; color: #fff; outline: none; border: none; cursor: pointer; transition: all 0.2s ease-in-out; text-decoration: none; margin-left: 24px; &:hover { transition: all 0.2s ease-in-out; background: #fff; color: #010606; } `; function Navbar(props) { return ( <> <Nav> <NavLink href='/'> <img alt='logo' /> </NavLink> <Bars /> <NavMenu> <NavLink href='/about' activeStyle> About </NavLink> <NavLink href='/services' activeStyle> Services </NavLink> <NavLink href='/contact-us' activeStyle> Contact Us </NavLink> <NavLink href='/sign-up' activeStyle> Sign Up </NavLink> </NavMenu> <NavBtn> <NavBtnLink href='/signin'>Sign In</NavBtnLink> </NavBtn> </Nav> </> ); } export default Navbar;
步骤3:创建对应路由页面
在pages目录下新建about.js、services.js、contact-us.js、sign-up.js、signin.js文件,Next.js会自动生成对应路由,无需额外配置。
方案2:仍要使用react-router-dom的临时修复方法
步骤1:修复命名冲突
删除Navbar.js中import {Router} from "next/router";这一行,避免重名覆盖。
步骤2:全局包裹Router上下文
新建/修改pages/_app.js文件,在最外层包裹路由容器:
import { BrowserRouter as Router } from 'react-router-dom'; function MyApp({ Component, pageProps }) { return ( <Router> <Component {...pageProps} /> </Router> ) } export default MyApp
注意:该方案在Next.js服务端渲染场景下可能出现更多兼容问题,不推荐长期使用。
内容的提问来源于stack exchange,提问作者Mahijendra
相关产品推荐
相关产品推荐

