在当前版本的React Router (v3)中,我可以接受服务器响应并使用browserHistory。点击进入相应的响应页面。但是,这在v4中是不可用的,我不确定处理它的适当方法是什么。

在这个例子中,使用Redux, components/app-product-form.js在用户提交表单时调用this.props. addproduct (props)。当服务器返回成功时,用户将被带到Cart页面。

// actions/index.js
export function addProduct(props) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
      .then(response => {
        dispatch({ type: types.AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/cart'); // no longer in React Router V4
      });
}

如何从React Router v4的函数重定向到购物车页面?


当前回答

React Router v4与v3(以及更早的版本)有本质上的不同,你不能像以前那样执行browserHistory.push()。

如果你想了解更多信息,这个讨论似乎是相关的:

创建一个新的browserHistory将不起作用,因为<BrowserRouter>创建了自己的历史实例,并侦听其上的更改。因此,不同的实例将更改url,但不更新<BrowserRouter>。 react-router不会在v4中公开browserHistory,只会在v2中公开。


相反,你有几个选择来做到这一点:

Use the withRouter high-order component Instead you should use the withRouter high order component, and wrap that to the component that will push to history. For example: import React from "react"; import { withRouter } from "react-router-dom"; class MyComponent extends React.Component { ... myFunction() { this.props.history.push("/some/Path"); } ... } export default withRouter(MyComponent); Check out the official documentation for more info: You can get access to the history object’s properties and the closest <Route>'s match via the withRouter higher-order component. withRouter will re-render its component every time the route changes with the same props as <Route> render props: { match, location, history }.


Use the context API Using the context might be one of the easiest solutions, but being an experimental API it is unstable and unsupported. Use it only when everything else fails. Here's an example: import React from "react"; import PropTypes from "prop-types"; class MyComponent extends React.Component { static contextTypes = { router: PropTypes.object } constructor(props, context) { super(props, context); } ... myFunction() { this.context.router.history.push("/some/Path"); } ... } Have a look at the official documentation on context: If you want your application to be stable, don't use context. It is an experimental API and it is likely to break in future releases of React. If you insist on using context despite these warnings, try to isolate your use of context to a small area and avoid using the context API directly when possible so that it's easier to upgrade when the API changes.

其他回答

我再提供一个解决方案,以防它对其他人有用。

我有一个history.js文件,其中我有以下内容:

import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history

接下来,在我定义路由器的根目录上,我使用以下命令:

import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'

export default class Root extends React.Component {
  render() {
    return (
     <Provider store={store}>
      <Router history={history}>
       <Switch>
        ...
       </Switch>
      </Router>
     </Provider>
    )
   }
  }

最后,在我的actions.js中,我导入历史并使用pushLater

import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)

这样,我可以在API调用之后推送到新的操作。

希望能有所帮助!

您可以在组件外部使用历史方法。试试下面的方法。

首先,使用历史包创建一个历史对象:

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

然后将它包装在<Router>中(请注意,你应该使用import {Router}而不是import {BrowserRouter as Router}):

// src/index.jsx

// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/login">Login</Link></li>
        </ul>
        <Route exact path="/" component={HomePage} />
        <Route path="/login" component={LoginPage} />
      </div>
    </Router>
  </Provider>,
  document.getElementById('root'),
);

从任何地方更改当前位置,例如:

// src/actions/userActionCreators.js

// ...
import history from '../history';

export function login(credentials) {
  return function (dispatch) {
    return loginRemotely(credentials)
      .then((response) => {
        // ...
        history.push('/');
      });
  };
}

UPD:你也可以在React Router FAQ中看到一个稍微不同的例子。

注意不要将react-router@5.2.0或react-router-dom@5.2.0与history@5.0.0连用。URL将在历史记录之后更新。推送或任何其他推送到历史指令,但导航不适用于react-router。使用NPM install history@4.10.1更改历史版本。参见升级到v5后,React路由器无法工作。

我认为这个问题发生在推动历史发生的时候。例如,使用<NavLink to="/apps">时,NavLink.js会消耗<RouterContext.Consumer>. js。上下文。当推送到历史记录时,位置将更改为具有动作和位置属性的对象。所以currentLocation。Pathname为空以匹配路径。

你可以像我这样使用它来登录和曼尼不同的东西

class Login extends Component {
  constructor(props){
    super(props);
    this.login=this.login.bind(this)
  }


  login(){
this.props.history.push('/dashboard');
  }


render() {

    return (

   <div>
    <button onClick={this.login}>login</login>
    </div>

)

This.context.history.push将不起作用。

我设法让推工作如下:

static contextTypes = {
    router: PropTypes.object
}

handleSubmit(e) {
    e.preventDefault();

    if (this.props.auth.success) {
        this.context.router.history.push("/some/Path")
    }

}