我刚刚把react-router从v3替换为v4。 但我不确定如何以编程方式在组件的成员函数中导航。 即在handleClick()函数中,我想在处理一些数据后导航到/path/some/where。 我以前是这样做的:

import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')

但是我在v4中找不到这样的界面。 如何使用v4导航?


当前回答

如果使用函数组件,请使用useHistory钩子

你可以使用useHistory钩子获取历史实例。

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

const MyComponent = () => {
  const history = useHistory();
  
  return (
    <button onClick={() => history.push("/about")}>
      Click me
    </button>
  );
}

useHistory钩子使您可以访问用于导航的历史实例。

在页面组件中使用history属性

React Router向页面组件注入一些属性,包括历史记录。

class HomePage extends React.Component {
  render() {
    const { history } = this.props;

    return (
      <div>
        <button onClick={() => history.push("/projects")}>
          Projects
        </button>
      </div>
    );
  }
}

用throuter包装子组件以注入路由器属性

withRouter包装器将路由器属性注入组件。例如,您可以使用此包装器注入路由器注销按钮组件放置在用户菜单。

import { withRouter } from "react-router";

const LogoutButton = withRouter(({ history }) => {
  return (
    <button onClick={() => history.push("/login")}>
      Logout
    </button>
  );
});

export default LogoutButton;

其他回答

我的答案和Alex的相似。我不知道为什么React-Router把这个做得如此复杂。为什么我必须用一个HoC来包装我的组件,只是为了访问本质上是全局的?

不管怎样,如果你看一下他们是如何实现<BrowserRouter>的,它只是一个历史记录的小包装。

我们可以把这段历史提取出来,这样我们就可以从任何地方导入。然而,诀窍在于,如果您正在进行服务器端呈现,并试图导入历史模块,那么它将无法工作,因为它使用的是纯浏览器api。但这没关系,因为我们通常只在响应单击或其他客户端事件时重定向。因此,假装一下是可以的:

// history.js
if(__SERVER__) {
    module.exports = {};
} else {
    module.exports = require('history').createBrowserHistory();
}

在webpack的帮助下,我们可以定义一些变量,这样我们就知道我们所处的环境:

plugins: [
    new DefinePlugin({
        '__SERVER__': 'false',
        '__BROWSER__': 'true', // you really only need one of these, but I like to have both
    }),

现在你可以

import history from './history';

从任何地方。它只会在服务器上返回一个空模块。

如果你不想使用这些神奇的变量,你只需要在需要它的全局对象中(在你的事件处理程序中)。导入不能工作,因为它只在顶层工作。

因为有时我更喜欢通过应用程序切换路由,然后通过按钮,这是一个最小的工作示例,对我有用:

import { Component } from 'react'
import { BrowserRouter as Router, Link } from 'react-router-dom'

class App extends Component {
  constructor(props) {
    super(props)

    /** @type BrowserRouter */
    this.router = undefined
  }

  async handleSignFormSubmit() {
    await magic()
    this.router.history.push('/')
  }

  render() {
    return (
      <Router ref={ el => this.router = el }>
        <Link to="/signin">Sign in</Link>
        <Route path="/signin" exact={true} render={() => (
          <SignPage onFormSubmit={ this.handleSignFormSubmit } />
        )} />
      </Router>
    )
  }
}

如此:

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

const SomeComponent = withRouter(({ history }) => (
    <div onClick={() => history.push('/path/some/where')}>
        some clickable element
    </div>); 
);

export default SomeComponent;

最简单的方法是:

this.props.history.push(“/new/url”)

注意:

如果历史道具不可用,你可以将它从父组件传递到你想调用该动作的组件。

你可以通过这种方式有条件地导航

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

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

  function handleClick() {
    history.push("/path/some/where");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}