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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:18:18