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

如何正确使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:15:31