如何正确使用React Router v6.4+与TypeScript?路由组件Hook报错求解
React Router v6.4+ 路由数组组件无法调用Hook的TypeScript解决方案
问题
使用react-router-dom v6.4+的路由对象数组实现路由功能时,路由跳转正常,但路由数组中element属性对应的组件内调用Hook(如useState)会触发控制台报错。尝试将element: MainLayout()改为element: <MainLayout/>时,TypeScript不允许此写法。
错误代码示例
route.ts
import MainLayout from './container/layouts/mainLayout/MainLayout' import ErrorPage from './view/Error' import Home from './view/Home' import { RouteObject, createBrowserRouter } from 'react-router-dom' const routes: RouteObject[] = [ { path: '/', element: MainLayout(), // 错误写法:直接调用组件函数 children: [ { index: true, element: Home(), // 同样错误 }, ], }, { path: '*', element: ChangeRoute('/404'), // 错误写法 }, { path: '/404', element: ErrorPage(), // 错误写法 }, ] const router = createBrowserRouter(routes) export default router
app.tsx
import { RouterProvider } from 'react-router-dom' import router from './route' function App() { return ( <RouterProvider router={router} fallbackElement={<React.Fragment>Loading ...</React.Fragment>} /> ) } export default App
MainLayout组件
import { useState } from 'react' import { Layout, Outlet } from 'antd' import SideBar from './SideBar' import Topbar from './Topbar' const MainLayout = () => { const [collapsed, setCollapsed] = useState(false) // 此处调用Hook会报错 return ( <Layout className='layout'> <SideBar collapsed={collapsed} /> <Layout> <Topbar collapsed={collapsed} setCollapsed={setCollapsed} /> <Outlet /> </Layout> </Layout> ) } export default MainLayout
解决方案
1. 修正路由数组的element写法
将直接调用组件函数的写法改为JSX元素写法,同时用react-router-dom内置的Navigate组件替代自定义的ChangeRoute:
import MainLayout from './container/layouts/mainLayout/MainLayout' import ErrorPage from './view/Error' import Home from './view/Home' import { RouteObject, createBrowserRouter, Navigate } from 'react-router-dom' const routes: RouteObject[] = [ { path: '/', element: <MainLayout />, // 正确写法:JSX元素 children: [ { index: true, element: <Home />, // 正确写法 }, ], }, { path: '*', element: <Navigate to="/404" replace />, // 使用内置Navigate组件处理重定向 }, { path: '/404', element: <ErrorPage />, // 正确写法 }, ] const router = createBrowserRouter(routes) export default router
2. 解决TypeScript类型报错
如果修改后TypeScript仍报错,检查并处理以下两点:
- 确保
RouteObject是从react-router-dom包导入,而非react-router - 若自定义组件存在类型冲突,可显式断言类型:
element: <MainLayout /> as React.ReactNode
原因说明
- 直接调用组件函数(如
MainLayout())会在路由初始化阶段执行组件代码,此时组件并未处于React的渲染流程中,违反了Hook只能在React组件渲染时调用的规则,因此触发报错。 - JSX元素写法(如
<MainLayout />)会创建一个React元素对象,由React Router在路由匹配时负责渲染,此时组件处于正常的React渲染流程,Hook可以正确调用。
内容的提问来源于stack exchange,提问作者Arijit
相关产品推荐
相关产品推荐

