面试题:在 React Router 中如何获取历史对象?

在 React Router 中,“历史对象”(history object)用于导航和管理浏览器的历史记录栈。获取历史对象的方式随着 React Router 版本的演进而变化,尤其在 v5 和 v6 之间有重大差异。

以下是不同版本中的获取方式:


React Router v6 (推荐版本)

在 v6 中,不再推荐直接访问 history 对象,而是提供了新的导航 Hook。

✅ 推荐方式:使用 useNavigate Hook

useNavigate 是 v6 中进行编程式导航的标准方式。它返回一个函数,用于导航到新位置。

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

function MyComponent() {
  const navigate = useNavigate();

  const handleClick = () => {
    // 导航到新路径
    navigate('/home');

    // 带状态导航
    navigate('/profile', { state: { from: 'dashboard' } });

    // 相对路径导航
    navigate('../settings');

    // 替换当前历史记录(不会留下记录)
    navigate('/login', { replace: true });

    // 后退
    navigate(-1);

    // 前进
    navigate(1);
  };

  return <button onClick={handleClick}>跳转</button>;
}

注意useNavigate 不能在组件外部使用(因为它是一个 Hook)。

⚠️ 替代方案:创建自定义 history(不推荐用于大多数场景)

如果确实需要类似 v5 的 history 对象(例如在组件外部导航),可以使用 createMemoryHistory 并结合 <Router>,但这通常用于特殊场景(如测试、非浏览器环境)。

// 不常用,仅作了解
import { createMemoryHistory } from 'history';

const customHistory = createMemoryHistory();

React Router v5 及更早版本

在 v5 中,可以通过多种方式获取 history 对象。

1. 使用 useHistory Hook (函数组件)

import { useHistory } from 'react-router-dom';

function MyComponent() {
  const history = useHistory();

  const handleClick = () => {
    history.push('/home');
    history.push('/profile', { from: 'dashboard' });
    history.replace('/login');
    history.goBack();
    history.goForward();
  };

  return <button onClick={handleClick}>跳转</button>;
}

2. 通过 withRouter 高阶组件 (HOC)

适用于类组件或需要将组件连接到路由的场景。

import { withRouter } from 'react-router-dom';

class MyComponent extends React.Component {
  handleClick = () => {
    this.props.history.push('/home');
  };

  render() {
    return <button onClick={this.handleClick}>跳转</button>;
  }
}

export default withRouter(MyComponent);

3. 路由组件自动注入 history props

如果组件是通过 <Route component={MyComponent} /> 渲染的,React Router 会自动向该组件注入 historylocationmatch 等 props。

function MyComponent({ history }) {
  const goHome = () => {
    history.push('/home');
  };
  return <button onClick={goHome}>首页</button>;
}

// 在 Route 中使用
<Route path="/dashboard" component={MyComponent} />

总结对比

方式适用版本推荐程度说明
useNavigate()v6✅ 强烈推荐v6 标准方式,返回导航函数
useHistory()v5✅ 推荐 (v5)v5 的 Hook 方式
withRouterv5⚠️ 可用适用于类组件或 HOC 场景
自动注入 historyv5⚠️ 可用仅限路由直接渲染的组件
createMemoryHistoryv6❌ 不推荐 (常规场景)用于特殊环境或自定义路由

核心要点

  • React Router v6 不再暴露 history 对象,而是用 useNavigate 取代。
  • 优先使用 Hook(如 useNavigateuseHistory)进行编程式导航。
  • 避免在组件外部直接使用 history,如果必须,考虑状态管理或事件总线。
  • 升级到 v6 时,需将 history.push 替换为 navigate 调用。

掌握这些方法,就能在不同版本的 React Router 中灵活实现页面导航。

THE END
喜欢就支持一下吧
点赞11 分享