如何获取React-Router v4的历史记录?


100

我从React-Router v3迁移到v4时遇到一些小问题。在v3中,我可以在任何地方执行此操作:

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

如何在v4中实现这一目标。

我知道withRouter当您在Component中时,可以使用hoc ,react上下文或事件路由器props。但对我而言并非如此。

我正在寻找v4中的NavigatingOutsideOfComponents的等效项


1
谢谢@克里斯,但是就像我说的那样,我不在Component中。
storm_buster

@Chris在实用程序类中,请检查github.com/ReactTraining/react-router/blob/master/docs/guides/…,它可能是redux中间件或其他内容
storm_buster


我最终使用BrowserRouter作为根组件。这样,我可以将App组件与Router一起使用。并非完全符合您的要求,但是我有相同的要求,这对我来说已经足够。
愚人节

Answers:


179

您只需要有一个导出history对象的模块。然后,您将在整个项目中导入该对象。

// history.js
import { createBrowserHistory } from 'history'

export default createBrowserHistory({
  /* pass a configuration object here if needed */
})

然后,您将使用该<Router>组件,而不是使用内置路由器之一。

// index.js
import { Router } from 'react-router-dom'
import history from './history'
import App from './App'

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder)
// some-other-file.js
import history from './history'
history.push('/go-here')

1
非常感谢!目前,使用react-router4,我不得不在history.js中使用此导入:从'history / createBrowserHistory'导入createBrowserHistory;
peter.bartos

3
当我在路线中放置history = {history}并像道具一样传递时,这对我来说非常有用
Nath Paiva

1
我们可以使用withHistory并在道具中获取历史记录,而不必创建单独的文件。这个解决方案不适用于redux。
Zeel Shah

4
createHashHistory如果使用,请导入HashRouter
David Harkness

2
@HassanAzzam您可能正在使用react-router V5,并且此答案适用于V4,而不是V5。我现在面临着同样的挑战,尽管到处都在寻找,但是却无法使它发挥作用。history.push在组件之外,但单击链接不再有效。
水联

71

这可行! https://reacttraining.com/react-router/web/api/withRouter

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

class MyComponent extends React.Component {
  render () {
    this.props.history;
  }
}

withRouter(MyComponent);

26
只要您在组件中。我不在组件内
–storm_buster

1
谢谢,这是从组件链接到另一条路线的最简单,最直接的方法。我要补充一点,您需要做一些this.props.history.push('/some_route');工作才能使它工作。
dannytenaglias

1
@storm_buster const Component = props => {... // stuff}export default withRouter(Component)在无状态组件上为我工作
Karl Taylor

10

Similiary到接受的答案是你可以做的是使用reactreact-router本身为您提供history对象,它可以在范围文件,然后出口。

history.js

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

// variable which will point to react-router history
let globalHistory = null;

// component which we will mount on top of the app
class Spy extends React.Component {
  constructor(props) {
    super(props)
    globalHistory = props.history; 
  }

  componentDidUpdate() {
    globalHistory = this.props.history;
  }

  render(){
    return null;
  }
}

export const GlobalHistory = withRouter(Spy);

// export react-router history
export default function getHistory() {    
  return globalHistory;
}

然后,您稍后导入Component并进行安装以初始化历史记录变量:

import { BrowserRouter } from 'react-router-dom';
import { GlobalHistory } from './history';

function render() {
  ReactDOM.render(
    <BrowserRouter>
        <div>
            <GlobalHistory />
            //.....
        </div>
    </BrowserRouter>
    document.getElementById('app'),
  );
}

然后,您可以在挂载应用程序时将其导入:

import getHistory from './history'; 

export const goToPage = () => (dispatch) => {
  dispatch({ type: GO_TO_SUCCESS_PAGE });
  getHistory().push('/success'); // at this point component probably has been mounted and we can safely get `history`
};

我什至制作了npm软件包来做到这一点。


从reactjs 16.9开始,此解决方案将对componentWillMount和componentWillReceiveProps发出弃用警告。
ian

1
@ian真实的,固定的
托马斯Mularczyk

5

如果您使用的是redux和redux-thunk,最好的解决方案是使用react-router-redux

// then, in redux actions for example
import { push } from 'react-router-redux'

dispatch(push('/some/path'))

查看文档进行一些配置很重要。


1
我来到这里是希望找到确切的解决方案,谢谢
vapurrmaid

4

如果仅需要历史对象以导航到其他组件,则基于此答案

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

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

  function handleClick() {
    history.push("/home");
  }

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

错误,您位于组件内。请参见//接受的答案中的some-other-
file.js

0

在App.js中

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

 const TheContext = React.createContext(null);

 const App = () => {
   const history = useHistory();

   <TheContext.Provider value={{ history, user }}>

    <Switch>
        <Route exact path="/" render={(props) => <Home {...props} />} />
        <Route
          exact
          path="/sign-up"
          render={(props) => <SignUp {...props} setUser={setUser} />}
        /> ...

然后在子组件中:

const Welcome = () => {
    
    const {user, history} = React.useContext(TheContext); 
    ....

-2

在的特定情况下react-router,使用context是有效的案例方案,例如

class MyComponent extends React.Component {
  props: PropsType;

  static contextTypes = {
    router: PropTypes.object
  };

  render () {
    this.context.router;
  }
}

您可以通过路由器上下文访问历史记录的实例,例如this.context.router.history


具体的问题是询问何时在组件外部,因此无法使用this.context:>“我知道在组件中时,可以使用hoRoute withRouter,react上下文或事件路由器道具。对我而言并非如此。”
SunshinyDoyle
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.