React Router Dom v6类组件替代RouteComponentProps的实现方案
适配react-router-dom v6的解决方案
在react-router-dom v6中,RouteComponentProps、history、match这些v5的API已被移除,取而代之的是useParams、useNavigate等钩子。以下提供两种适配方案:
方案一:重构为函数组件(推荐)
函数组件可直接使用v6的原生钩子,代码更简洁易维护:
import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import TutorialService from '../../services/TutorialService'; import { ITutorialData } from '../../types/tutorial.type'; export default function Tutorial() { // 获取路由参数id const { id } = useParams<{ id: string }>(); // 获取导航方法 const navigate = useNavigate(); const [currentTutorial, setCurrentTutorial] = useState<ITutorialData>({ id: null, title: "", description: "", published: false, }); const [message, setMessage] = useState<string>(""); // 原组件的事件处理函数保留,示例: const onChangeTitle = (e: React.ChangeEvent<HTMLInputElement>) => { setCurrentTutorial({ ...currentTutorial, title: e.target.value }); }; const onChangeDescription = (e: React.ChangeEvent<HTMLTextAreaElement>) => { setCurrentTutorial({ ...currentTutorial, description: e.target.value }); }; const getTutorial = (tutorialId: string) => { TutorialService.get(tutorialId) .then((response: any) => { setCurrentTutorial(response.data); console.log(response.data); // 修正原代码笔误:response.date → response.data }).catch((e: Error) => { console.log(e); }); }; const updatePublished = () => { // 保留原业务逻辑 }; const updateTutorial = () => { // 保留原业务逻辑 }; const deleteTutorial = () => { TutorialService.remove(currentTutorial.id) .then((resp: any) => { console.log(resp.data); navigate("/tutorials"); // 替代v5的history.push }).catch((e: Error) => { console.log(e); }); }; // 替代componentDidMount,路由参数变化时自动重新获取数据 useEffect(() => { if (id) { getTutorial(id); } }, [id]); return ( <div>Tutorial</div> ); }
方案二:为类组件创建高阶组件(HOC)
若不想重构为函数组件,可自定义HOC注入路由相关能力:
第一步:实现withRouter高阶组件
// src/hocs/withRouter.tsx import React from 'react'; import { useParams, useNavigate, Params, NavigateFunction } from 'react-router-dom'; interface WithRouterProps { params: Params<string>; navigate: NavigateFunction; } export function withRouter<T extends {}>(Component: React.ComponentType<T & WithRouterProps>) { return function WrappedComponent(props: Omit<T, keyof WithRouterProps>) { const params = useParams(); const navigate = useNavigate(); return <Component {...(props as T)} params={params} navigate={navigate} />; }; }
第二步:修改原类组件代码
import React, { Component, ChangeEvent } from 'react'; import TutorialService from '../../services/TutorialService'; import { ITutorialData } from '../../types/tutorial.type'; import { withRouter } from '../hocs/withRouter'; // 导入自定义HOC // 定义组件接收的props interface Props { params: { id: string }; navigate: (to: string) => void; }; type State = { currentTutorial: ITutorialData, message: string, }; class Tutorial extends Component<Props, State> { constructor(props: Props) { super(props); this.onChangeTitle = this.onChangeTitle.bind(this); this.onChangeDescription = this.onChangeDescription.bind(this); this.getTutorial = this.getTutorial.bind(this); this.updatePublished = this.updatePublished.bind(this); this.updateTutorial = this.updateTutorial.bind(this); this.deleteTutorial = this.deleteTutorial.bind(this); this.state = { currentTutorial: { id: null, title: "", description: "", published: false, }, message: "", }; } componentDidMount(): void { this.getTutorial(this.props.params.id); // 从注入的params获取路由id }; // 监听路由参数变化,更新数据 componentDidUpdate(prevProps: Props): void { if (prevProps.params.id !== this.props.params.id) { this.getTutorial(this.props.params.id); } } getTutorial(id: string) { TutorialService.get(id) .then((response: any) => { this.setState({ currentTutorial: response.data, }); console.log(response.data); // 修正原代码笔误 }).catch((e: Error) => { console.log(e); }); }; deleteTutorial() { TutorialService.remove(this.state.currentTutorial.id) .then((resp: any) => { console.log(resp.data); this.props.navigate("/tutorials"); // 用注入的navigate替代history.push }).catch((e: Error) => { console.log(e); }) } onChangeTitle(e: ChangeEvent<HTMLInputElement>) { this.setState({ currentTutorial: { ...this.state.currentTutorial, title: e.target.value } }); } onChangeDescription(e: ChangeEvent<HTMLTextAreaElement>) { this.setState({ currentTutorial: { ...this.state.currentTutorial, description: e.target.value } }); } updatePublished() { // 保留原业务逻辑 } updateTutorial() { // 保留原业务逻辑 } render() { return ( <div>Tutorial</div> ) } } // 用withRouter包装组件,注入路由能力 export default withRouter(Tutorial);
核心变化说明
- 移除
RouteComponentProps相关依赖,改用v6原生钩子或自定义HOC - 路由参数获取:v5的
match.params.id→ v6的useParams()或HOC注入的params - 页面导航:v5的
history.push→ v6的navigate函数 - 类组件需手动监听路由参数变化(
componentDidUpdate),函数组件通过useEffect自动处理
内容的提问来源于stack exchange,提问作者Ali Hamza Rao
相关产品推荐
相关产品推荐

