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

React TypeScript中BrowserRouter编程式路由跳转TS2339错误

解决React Router中window.history.push的类型错误

这个问题我之前也碰到过,核心原因是你把浏览器原生的History API和React Router封装的history对象搞混了!浏览器原生的window.history根本没有push方法(它对应的是pushState),而你需要的无刷新路由跳转,得用React Router提供的导航方式才行。结合你说的「Router是当前组件的子元素」这个场景,给你两种主流版本的解决方案:

React Router v6+(当前主流版本)

因为你的myPage组件是Router的父组件(Router通过props.children传入),所以直接在myPage里用useNavigate钩子是不行的——路由钩子只能在Router上下文内部的组件中使用。这里有两种处理思路:

思路1:把导航逻辑移到Router内部组件

这是最符合React Router设计的方式,把点击跳转的逻辑放到Router内部的页面组件里,这样就能正常使用useNavigate:

import React from 'react';
import { useNavigate } from 'react-router-dom';

// 定义Router内部的导航组件
const NavTrigger: React.FC = () => {
  const navigate = useNavigate();

  const loadPage = (event: React.MouseEvent<HTMLDivElement>) => {
    const target = event.target as HTMLDivElement;
    if (target.id) {
      navigate(`/${target.id}`); // 用React Router的导航方法
    }
  };

  return <div id='home' onClick={loadPage}></div>;
};

// 你的myPage组件
const myPage: React.FC = (props) => {
  return (
    <>
      {/* 渲染Router内部的导航组件 */}
      <NavTrigger />
      <section>
        {props.children} {/* 这里是你的BrowserRouter */}
      </section>
    </>
  );
};

思路2:自定义History实例(适合必须在Router外部导航的场景)

如果你确实需要在Router父组件里处理跳转,可以创建一个自定义的history实例,传递给BrowserRouter:

首先安装依赖:

npm install history

然后修改代码:

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { createBrowserHistory } from 'history';

// 创建自定义history实例
const history = createBrowserHistory();

const myPage: React.FC = (props) => {
  const loadPage = (event: React.MouseEvent<HTMLDivElement>) => {
    const target = event.target as HTMLDivElement;
    if (target.id) {
      history.push(`/${target.id}`); // 用自定义实例的push方法
    }
  };

  return (
    <>
      <div id='home' onClick={loadPage}></div>
      <section>
        {/* 把自定义history传给BrowserRouter */}
        <BrowserRouter history={history}>
          {props.children}
        </BrowserRouter>
      </section>
    </>
  );
};

React Router v5(旧版本兼容)

如果还在使用React Router v5,同样分两种情况:

思路1:用withRouter高阶组件(Router内部组件)

把myPage用withRouter包装,让它能获取到React Router的history对象:

import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';

// 定义props类型
type MyPageProps = RouteComponentProps & {
  children: React.ReactNode;
};

const myPage: React.FC<MyPageProps> = (props) => {
  const loadPage = (event: React.MouseEvent<HTMLDivElement>) => {
    const target = event.target as HTMLDivElement;
    if (target.id) {
      props.history.push(`/${target.id}`);
    }
  };

  return (
    <>
      <div id='home' onClick={loadPage}></div>
      <section>
        {props.children}
      </section>
    </>
  );
};

// 用withRouter包装组件
export default withRouter(myPage);

思路2:自定义History实例(Router外部)

和v6的思路一致,创建自定义history实例并传给BrowserRouter即可,代码和v6版本几乎相同。

额外提醒

别想着用window.history.pushState来跳转——虽然它能改URL,但React Router不会感知到这个变化,也就不会更新对应的路由组件,等于白折腾。必须用React Router提供的导航方法,才能实现真正的无刷新路由跳转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:24:32