You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用react-router-dom v6路由组件时出现createHref读取未定义错误求助

问题:React Router v6 路由跳转报错 Uncaught TypeError: Cannot read properties of undefined (reading 'createHref')

尝试使用react-router-dom v6实现组件路由跳转时触发该错误,当前项目使用styled-components,不确定是否与此问题相关。路由定义在App.js中,负责跳转的按钮组件在SideBySideButtons.js中,核心代码如下:

App.js

import React from 'react';
import { Routes, Route, Router } from 'react-router-dom';

import Landing from './components/Landing';
import EarlyAccess from './components/LandingPages/EarlyAccess';

import WebFont from 'webfontloader';

if (process.env.NODE_ENV === 'development') {
  WebFont.load({
    google: {
      families: ['Barlow', 'Playfair Display', 'Overpass']
    }
  });
}

/* 
Rather than create a memory history object inside app.js, we create it in bootstrap.js because we want to customize it quite a bit
*/
export default ({ history }) => {

  return (
    <div>
      <Router location={history.location} history={history}>
        <Routes>
          <Route exact path="/earlyaccess" element={ <EarlyAccess /> } />
          <Route exact path="/learn" element={ <EarlyAccess /> } />
          <Route path="/" element={ <Landing /> } />
        </Routes>
      </Router>
    </div>
  );
};

SideBySideButtons.js

import React from 'react';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';

const DisplayBlock = styled.div`
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
  -webkit-justify-content: space-between;
  -ms-flex-pack: justify;
  justify-content: center;
  border-radius: 3px;
  -webkit-transition: all 350ms ease;
  transition: all 350ms ease;
  color: #000;
  font-size: 16px;
  text-transform: uppercase;

  @media screen and (max-width: 767px) {
    padding-top: 10px;
  }
`

const EarlyAccessLink = styled(RouterLink).attrs({ to: '/earlyaccess'})`
  display: inline-block;
  padding: 9px 15px;
  margin-top: 20px;

  border: 0;
  border-radius: 3px;

  font-family: 'Playfair Display', sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: inherit;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  
  background-color: #0c0a89;
  color: #fff;

  -webkit-transition: all 350ms ease;
  transition: all 350ms ease;
  
  &:hover {
    background-color: #09d5b0;
    -webkit-transform: translate(0px, -2px);
    -ms-transform: translate(0px, -2px);
    transform: translate(0px, -2px);
    text-decoration: none;
  }

  @media screen and (max-width: 991px) {
    padding-right: 15px;
    padding-left: 15px;
  }
`

const LearnMoreLink = styled(RouterLink).attrs({ to: '/learn'})`
  cursor: pointer;

  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  margin-top: 20px;
  margin-left: 15px;
  padding: 9px 15px;

  -webkit-box-pack: justify;
  -webkit-justify-content: space-between;
  -ms-flex-pack: justify;
  justify-content: space-between;

  border-style: solid;
  border-width: 1px;
  border-color: #15113b;
  border-radius: 3px;

  -webkit-transition: all 350ms ease;
  transition: all 350ms ease;

  background-color: transparent;
  color: #0c0a89;
  font-family: 'Playfair Display', sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: inherit;
  text-decoration: none;
  text-transform: uppercase;
  
  @media screen and (max-width: 991px) {
    padding-right: 15px;
    padding-left: 15px;
  }

  &:hover {
    background-color: #15113b;
    border-color: #ffd343;
    color: #fff;
    box-shadow: 1px 1px 12px 0 rgba(0, 0, 0, 0.08);
    text-decoration: none;
    -webkit-transform: translate(0px, -2px);
    -ms-transform: translate(0px, -2px);
    transform: translate(0px, -2px);
    text-decoration: none;
  }
`

export default function Buttons() {
  return (
    <React.Fragment>
      <DisplayBlock>
          <EarlyAccessLink>Early Access</EarlyAccessLink>
          <LearnMoreLink>Learn More</LearnMoreLink>
      </DisplayBlock>
    </React.Fragment>
  )
}
解决方案

该错误与styled-components无关,核心原因是react-router-dom v6中<Router>组件的API发生了变化:

  • v6的<Router>不再接受history属性,而是需要navigator属性
  • 自定义history对象的传递方式不符合v6要求,导致路由上下文无法正确初始化,<Link>组件找不到createHref等路由方法

修复方案1:使用内置<BrowserRouter>(推荐)

如果不需要自定义history逻辑,直接替换为v6内置的<BrowserRouter>即可,它会自动处理history:

import React from 'react';
// 替换Router为BrowserRouter
import { Routes, Route, BrowserRouter } from 'react-router-dom';

import Landing from './components/Landing';
import EarlyAccess from './components/LandingPages/EarlyAccess';

import WebFont from 'webfontloader';

if (process.env.NODE_ENV === 'development') {
  WebFont.load({
    google: {
      families: ['Barlow', 'Playfair Display', 'Overpass']
    }
  });
}

export default () => {
  return (
    <div>
      <BrowserRouter>
        <Routes>
          {/* v6中Route默认精确匹配,无需exact属性 */}
          <Route path="/earlyaccess" element={ <EarlyAccess /> } />
          <Route path="/learn" element={ <EarlyAccess /> } />
          <Route path="/" element={ <Landing /> } />
        </Routes>
      </BrowserRouter>
    </div>
  );
};

注意:v6的<Route>组件不再支持exact属性,默认采用精确匹配规则。

修复方案2:自定义history(仅当需要时使用)

如果必须使用自定义history(比如内存history用于测试),需要使用history库创建history对象,并传递给<Router>的navigator属性:

import React from 'react';
import { Routes, Route, Router } from 'react-router-dom';
// 导入history库创建自定义history
import { createBrowserHistory } from 'history';

import Landing from './components/Landing';
import EarlyAccess from './components/LandingPages/EarlyAccess';

import WebFont from 'webfontloader';

const history = createBrowserHistory();

if (process.env.NODE_ENV === 'development') {
  WebFont.load({
    google: {
      families: ['Barlow', 'Playfair Display', 'Overpass']
    }
  });
}

export default () => {
  return (
    <div>
      {/* v6中传递navigator而非history */}
      <Router location={history.location} navigator={history}>
        <Routes>
          <Route path="/earlyaccess" element={ <EarlyAccess /> } />
          <Route path="/learn" element={ <EarlyAccess /> } />
          <Route path="/" element={ <Landing /> } />
        </Routes>
      </Router>
    </div>
  );
};

验证

你的SideBySideButtons.js中对RouterLink的styled-components封装是正确的,只要路由上下文正常传递,就能正常触发跳转,无需修改该文件代码。

内容的提问来源于stack exchange,提问作者melv3223

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:54:24