如何在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组件的类型定义:
- 修改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;
- 修正Header组件的useRef类型(避免使用
any)
// 将原有的 const headerRef:any = useRef(null); 修改为 const headerRef = useRef<HTMLDivElement>(null);
方案二:若需通过render传递自定义props
如果确实要给Header传递自定义props,需正确处理TypeScript类型:
- 给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); // 剩余代码保持不变... }
- 给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
相关产品推荐
相关产品推荐

