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

如何在TypeScript中使用react-router-dom v5的Route render属性

在TypeScript中正确使用react-router-dom v5 Route组件的render属性

我将React项目从JavaScript转为TypeScript后,在App组件中使用react-router-dom v5的Route组件render属性传递props给Header时出现错误,以下是相关代码及依赖配置,求正确实现方式。

相关代码

App组件

import 'swiper/swiper.min.css';
import './assets/boxicons-2.0.7/css/boxicons.min.css';
import './App.scss';
import { BrowserRouter, Route } from 'react-router-dom';
import Header from './components/header/Header';
import Footer from './components/footer/Footer';
import Routes from './config/Routes';

function App() {
  return (
    <BrowserRouter>
      <Route
        render={props => (
          <>
            <Header {...props} />
            <Routes />
            <Footer />
          </>
        )}
      />
    </BrowserRouter>
  );
}

export default App;

Header组件

import { useRef, useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import './header.scss';
import logo from '../../assets/tmovie.png';

const headerNav = [
    {
        display: 'Home',
        path: '/'
    },
    {
        display: 'Movies',
        path: '/movie'
    },
    {
        display: 'TV Series',
        path: '/tv'
    }
];

const Header = () => {

    const { pathname } = useLocation();
    const headerRef:any = useRef(null);

    const active = headerNav.findIndex(e => e.path === pathname);

    useEffect(() => {
        const shrinkHeader = () => {
            if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 100) {
                headerRef.current.classList.add('shrink');
            } else {
                headerRef.current.classList.remove('shrink');
            }
        }
        window.addEventListener('scroll', shrinkHeader);
        return () => {
            window.removeEventListener('scroll', shrinkHeader);
        };
    }, []);

    return (
        <div ref={headerRef} className="header">
            <div className="header__wrap container">
                <div className="logo">
                    <img src={logo} alt="" />
                    <Link to="/">tMovies</Link>
                </div>
                <ul className="header__nav">
                    {
                        headerNav.map((e, i) => (
                            <li key={i} className={`${i === active ? 'active' : ''}`}>
                                <Link to={e.path}>
                                    {e.display}
                                </Link>
                            </li>
                        ))
                    }
                </ul>
            </div>
        </div>
    );
}

export default Header;

依赖配置

{
  "name": "dummy",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "axios": "^1.4.0",
    "prop-types": "^15.8.1",
    "query-string": "^8.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^5.3.0",
    "sass": "^1.62.1",
    "swiper": "^6.8.4"
  },
  "devDependencies": {
    "@types/react": "^18.0.37",
    "@types/react-dom": "^18.0.11",
    "@types/react-router-dom": "^5.3.3",
    "@typescript-eslint/eslint-plugin": "^5.59.0",
    "@typescript-eslint/parser": "^5.59.0",
    "@vitejs/plugin-react": "^4.0.0",
    "eslint": "^8.38.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.3.4",
    "typescript": "^5.0.2",
    "vite": "^4.3.9"
  }
}

解决方案

你的问题核心有两点:一是Header组件未定义Props类型,二是你其实不需要通过Route的render传递路由props——Header内部已经使用useLocation Hook,可直接获取路由信息,无需依赖外部传入的props。下面提供两种方案:

方案一:移除不必要的props传递(推荐)

直接简化App组件的写法,同时修正Header组件的类型定义:

  1. 修改App组件
import 'swiper/swiper.min.css';
import './assets/boxicons-2.0.7/css/boxicons.min.css';
import './App.scss';
import { BrowserRouter } from 'react-router-dom';
import Header from './components/header/Header';
import Footer from './components/footer/Footer';
import Routes from './config/Routes';

function App() {
  return (
    <BrowserRouter>
      <Header />
      <Routes />
      <Footer />
    </BrowserRouter>
  );
}

export default App;
  1. 修正Header组件的useRef类型(避免使用any)
// 将原有的 const headerRef:any = useRef(null); 修改为
const headerRef = useRef<HTMLDivElement>(null);

方案二:若需通过render传递自定义props

如果确实要给Header传递自定义props,需正确处理TypeScript类型:

  1. 给Header组件定义Props类型
import { Link, useLocation, RouteComponentProps } from 'react-router-dom';

// 定义Props类型,包含路由props和自定义props
type HeaderProps = RouteComponentProps & {
  // 可添加自定义props,比如:customTitle?: string
};

// 让Header接收props
const Header = (props: HeaderProps) => {
  // 可直接使用传入的路由props,比如 props.history
  const { pathname } = useLocation();
  const headerRef = useRef<HTMLDivElement>(null);
  
  // 剩余代码保持不变...
}
  1. 给App组件的Route render函数指定props类型
import { BrowserRouter, Route, RouteComponentProps } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Route
        render={(props: RouteComponentProps) => (
          <>
            <Header {...props} />
            <Routes />
            <Footer />
          </>
        )}
      />
    </BrowserRouter>
  );
}

额外优化建议

  • 移除prop-types依赖,TypeScript已提供类型检查能力,无需重复配置
  • 给headerNav数组添加类型定义,增强类型安全:
type NavItem = {
  display: string;
  path: string;
};

const headerNav: NavItem[] = [
    { display: 'Home', path: '/' },
    { display: 'Movies', path: '/movie' },
    { display: 'TV Series', path: '/tv' }
];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:07:27