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

React Router 5类组件点击按钮触发路由跳转实现方案

错误原因

useHistory是React Router提供的Hook API,Hook仅允许在函数组件顶层作用域、或自定义Hook内部调用。你在类组件的实例方法中调用useHistory,违反了Hook的调用规则,因此抛出Invalid hook call错误。

适配react-router-dom@5.3.0的实现方案

类组件中不要使用Hook实现跳转,可通过以下两种官方支持的方式实现和Link完全一致的无刷新前端路由跳转:

方案1:使用withRouter高阶组件(推荐)

withRouter是React Router v5专门为类组件提供的高阶组件,会自动将history/location/match三个路由对象注入到组件的props中。
注意:被withRouter包裹的组件必须放置在<Router>组件的子树范围内才能获取到路由上下文,因此需要先调整代码结构:

  1. 将<Router>组件移动到应用入口文件(通常为src/index.js),包裹根组件App:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';

ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById('root')
);
  1. 修改App组件,移除内部的Router声明,引入withRouter包裹组件后直接通过props访问history实现跳转:
import React from 'react';
import { Link, Route, Switch, withRouter } from 'react-router-dom';

// Import pages
import Page1 from './pages/page-1';
import Page2 from './pages/page-2';

class App extends React.Component {    
  navigateToPage1 = () => {
    this.props.history.push('/page-1');
  }

  navigateToPage2 = () => {
    this.props.history.push('/page-2');
  }

  render() {
    return(
      <div className="container p-3 mx-auto">
        <div className="pb-2">    
          <button onClick={this.navigateToPage1}>Visit Page 1</button>
          <button onClick={this.navigateToPage2}>Visit Page 2</button>

          <Link to="/page-1">Page 1</Link> 
          <Link to="/page-2">Page 2</Link> 
        </div>

        <div>
          <Switch>
            <Route exact path="/">
              <Page1 />
            </Route>

            <Route path="/page-1">
              <Page1 />
            </Route>

            <Route path="/page-2">
              <Page2 />
            </Route>    
          </Switch>
        </div>  
      </div>
    );
  }
}

export default withRouter(App);

方案2:抽离子组件接入路由(无需调整Router位置)

如果你不想把Router移到App外层,可以把需要触发跳转的导航区域抽成独立类组件,用withRouter包裹后放在Router内部即可:

import React from 'react';
import { Link, BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';

// Import pages
import Page1 from './pages/page-1';
import Page2 from './pages/page-2';

// 抽离导航组件
class NavSection extends React.Component {
  navigateToPage1 = () => {
    this.props.history.push('/page-1');
  }
  navigateToPage2 = () => {
    this.props.history.push('/page-2');
  }
  render() {
    return <div className="pb-2">    
      <button onClick={this.navigateToPage1}>Visit Page 1</button>
      <button onClick={this.navigateToPage2}>Visit Page 2</button>
      <Link to="/page-1">Page 1</Link> 
      <Link to="/page-2">Page 2</Link> 
    </div>
  }
}
const WrappedNavSection = withRouter(NavSection);

class App extends React.Component {    
  render() {
    return(
      <div className="container p-3 mx-auto">
        <Router> 
          <WrappedNavSection />
          <div>
            <Switch>
              <Route exact path="/">
                <Page1 />
              </Route>
              <Route path="/page-1">
                <Page1 />
              </Route>
              <Route path="/page-2">
                <Page2 />
              </Route>    
            </Switch>
          </div>  
        </Router>
      </div>
    );
  }
}

export default App;

以上两种方案的跳转逻辑和Link组件完全一致,均基于HTML5 History API实现前端路由切换,不会触发浏览器整页刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:06:36