react create-react-app v5 配置路由(报错及注意事项)

文章讲述了在使用ReactRouterv6时遇到的TypeError错误,主要集中在如何解决在BrowserRouter中useRef的报错,涉及清除缓存、node_modules操作以及不同路由组件的选择和配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

报错信息:

Uncaught TypeError: Cannot read properties of null (reading ‘useRef’)

The above error occurred in the component:
at BrowserRouter (http://localhost:3000/static/js/bundle.js:4864:5)
at App Consider adding an error boundary to your tree to customize error handling behavior.
报错截图
在这里插入图片描述

解决方案:

我的环境是:

    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router": "^6.16.0",
    "react-router-dom": "^6.16.0",

create-react-app v5

我遇到这个问题时,一开始怀疑语法问题,但最后都排除了。
我的解决方案是:
1.先尝试 清除缓存 执行npm cache clean --force
2.npm start看看行不行
3.如果不行的话,删除node_moudels 然后再cnpm install (我试了几次都可以)
4.最后 npm start就可以了
我还尝试过 npm uninstall react-router-dom 然后再重新下载也不行。

我觉得原因 可能是node_modules下的.store里造成的,我单独删除 .cache 不行,然后删除.store 直接报错。最后删除整个node_modules才行的。

配置路由的步骤:

1.首先 npm react-router-dom
2.App.js 里 写上如下代码:

import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import routes from './routes';
const App = () => {
  console.log(routes)
  return (
    <BrowserRouter>
      <Routes>
        {routes.map((route) => (
          <Route key={route.path} path={route.path} element={route.component} />
        ))}
        {/* <Route path="*" element={<Home />} />  */}
      </Routes>
    </BrowserRouter>
  );
};

export default App;

App.js 代码截图
3.index.js里写上:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
   </React.StrictMode> 
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

index.js代码截图

4.在src下新建一个 routes.js文件 写上:

// 导入你的页面组件  
import Home from './pages'; 
const routes = [
  { path: "/", component: <Home/>}
];

export default routes;

routes.js代码截图
运行看到 Home组件里的东西就说明成功了。之后可以在 scr/router.js里导入其他组件 写上 path和routers就行了。

注意:react-router-dom v6 和v5 api不太一样,比如 v5 把 Route 上是 component v6是element。具体写法 建议参考 你所用的版本 文档!

注意:BrowserRouter 是 不带井号的,所以 部署时后端需要 配合一下 比如:重定向到 index.html
具体配置,建议自行查阅。
比如:在Tomcat的web.xml文件中添加以下配置,以将所有请求重定向到应用程序的入口文件上:

<web-app>
  <!-- ... -->
  <error-page>
    <error-code>404</error-code>
    <location>/your-app-name/index.html</location>
  </error-page>
</web-app>

如果你有需要部署到非根目录建议可以参考:create-react-app v5 打包配置(部署到非根目录)

react-router-dom v6 路由模式

BrowserRouter

优点:

  • 使用HTML5的history API,通过修改URL的路径和查询参数来管理路由状态。

  • 可以在URL中显示清晰的路由信息,不会使用#符号。

  • 支持通过直接输入URL或使用浏览器的前进/后退按钮导航到特定的路由。

缺点:

  • 当刷新页面时,向后端服务器发出请求,需要在服务器上进行相应的配置,以确保在前端应用中正确加载页面。

使用方法:

import React from "react";
import { BrowserRouter, Routes, Route , MemoryRouter , HashRouter} from "react-router-dom";
import routes from "./routes.js";
const App = () => {
  return (
    // basename="/fund_diag_h5"
    <BrowserRouter>
      <Routes>
        {routes.map((route) => (
           <Route key={route.path} path={route.path} element={route.component} />
        ))}

        {/* <Route path="/detail/:fundCode" element={<FundDetail />} /> */}
      </Routes>
    </BrowserRouter>
  );
};

export default App;

这个是官方推荐的路由方式,使用最多,不过需要后端配合!

使用场景:

  • 需要在URL中显示清晰的路由信息,并且支持直接输入URL或使用浏览器的前进/后退按钮导航到特定路由的场景。

  • 需要支持搜索引擎优化(SEO)的应用。

HashRouter

优点:

  • 使用哈希路由,通过在URL中添加#符号和哈希值来管理路由状态,可以在前端应用中实现基本的路由功能。

  • 可以方便地通过直接输入URL或使用浏览器的前进/后退按钮导航到特定的路由。

缺点:

  • URL中会带有#符号,对一些用户来说可能不太友好。

  • 可能会存在一些兼容性问题,某些情况下哈希部分的URL可能会被忽略(比如:微信里就会把#后的东西截取掉)。

使用方法:

import React from "react";
import { BrowserRouter, Routes, Route , MemoryRouter , HashRouter} from "react-router-dom";
import routes from "./routes.js";
const App = () => {
  return (
    // basename="/fund_diag_h5"
    <HashRouter>
      <Routes>
        {routes.map((route) => (
           <Route key={route.path} path={route.path} element={route.component} />
        ))}

        {/* <Route path="/detail/:fundCode" element={<FundDetail />} /> */}
      </Routes>
    </HashRouter>
  );
};

export default App;

这个方式,也挺常见的,因为方便不需要后端配合,但是 致命缺点就是 url里有#号!

使用场景:

  • 需要在URL中显示路由信息,并且需要支持直接输入URL或使用浏览器的前进/后退按钮导航到特定路由的场景。

  • 对搜索引擎友好性要求不高的一些应用。

MemoryRouter

优点:

  • 内存中的路由状态管理,不会反映在URL上,不会导致页面刷新和跳转。

  • 适用于不需要在URL中显示路由信息,或在一些特殊场景中使用,如测试或某些客户端应用程序,可以使用内存中的路由状态进行导航和渲染。

缺点:

  • 无法通过直接输入URL或通过浏览器前进/后退按钮导航到特定路由。

  • 不支持搜索引擎爬取。搜索引擎无法通过内存中的路由状态获得页面内容。

使用方法:

import React from "react";
import { BrowserRouter, Routes, Route , MemoryRouter , HashRouter} from "react-router-dom";
import routes from "./routes.js";
const App = () => {
  return (
    // basename="/fund_diag_h5"
    <MemoryRouter>
      <Routes>
        {routes.map((route) => (
           <Route key={route.path} path={route.path} element={route.component} />
        ))}

        {/* <Route path="/detail/:fundCode" element={<FundDetail />} /> */}
      </Routes>
    </MemoryRouter>
  );
};

export default App;

这个一般很少使用。
怎么理解:内存中的路由状态管理,不会反映在URL上,不会导致页面刷新和跳转?
我尝试了一下:
就是如果你路由传参,参数不会显示到url地址栏里:
比如: navigate(/detail?fundCode=${data.fundCode}) 跳转到详情页但是 后面的?fundCode被忽略了
而且浏览器 后退,前进 失效了。

 navigate(`/detail?fundCode=${data.fundCode}`)

如果部署到非根目录,则不用家basename 也可以正常显示。

适用场景:

  • 不需要在URL中显示路由信息,或在一些特殊的客户端应用程序中,可以使用内存中的路由状态进行导航和渲染。

  • 单元测试等需要在不刷新页面的情况下进行路由状态管理的场景。

实现动态 title

title截图
react-router v6实现动态的title(react-router-dom v6)

总结:

根据具体的需求和应用场景,选择合适的路由组件来管理你的应用程序的导航和页面渲染。如果不需要在URL中显示路由信息,则可以使用MemoryRouter;如果需要使用哈希路由,并且不介意URL中的#符号,则可以使用HashRouter;如果需要在URL中显示清晰的路由信息,并且支持直接输入URL或使用浏览器的前进/后退按钮导航到特定路由,则可以使用BrowserRouter。

路由组件内存历史记录(MemoryRouter)哈希路由(HashRouter)浏览器历史记录(BrowserRouter)
功能在内存中管理路由状态,不会反映在URL上,不会导致页面刷新和跳转。使用URL中的哈希路由,通过添加#符号和哈希值来管理路由状态。使用HTML5的history API,通过修改URL的路径和查询参数来管理路由状态。
URL显示不显示显示,带有#符号显示,清晰的URL路径和查询参数。
页面刷新无法刷新页面,不会向服务器发送请求可以刷新页面,但仍在前端应用中加载,不会向服务器发送请求可以刷新页面,在刷新时向服务器发送请求
导航和跳转无法通过直接输入URL或浏览器前进/后退按钮导航到特定路由,适用于内存导航或特殊场景。可以通过直接输入URL或浏览器前进/后退按钮导航到特定路由,适用于基本路由需求。可以通过直接输入URL或浏览器前进/后退按钮导航到特定路由,适用于清晰路由需求和SEO优化。
搜索引擎优化不支持不支持支持
适用场景- 不需要在URL中显示路由信息 - 测试目的 - 特殊客户端应用程序需要在URL中显示路由信息 - 不要求搜索引擎优化的前端应用程序- 需要在URL中显示清晰的路由信息 - 需要搜索引擎优化的应用程序

请注意,上述表格是根据对每种路由组件的特性进行的总结,并非完整的列表。你在选择适合你应用程序的路由组件时,还要考虑其他因素,例如性能、需求复杂度和开发团队的熟悉程度等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

崽崽的谷雨

漫漫前端路,摸爬滚打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值