如何在 React Router v4 中推送到历史记录?

在当前版本的 React Router (v3) 中,我可以接受服务器响应并使用 browserHistory.push 转到相应的响应页面。但是,这在 v4 中不可用,我不确定处理此问题的适当方法是什么。

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

 // 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 的功能重定向到购物车页面?

原文由 Chris 发布,翻译遵循 CC BY-SA 4.0 许可协议
阅读 1.4k
2 个回答

您可以在组件之外使用 history 方法。通过以下方式尝试。

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

 // 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 中看到一个稍微不同的例子。

原文由 Oleg Belostotsky 发布,翻译遵循 CC BY-SA 3.0 许可协议

React Router v4 从根本上不同于 v3(及更早版本),您不能像以前那样做 browserHistory.push()

如果您想了解更多信息, 此讨论 似乎相关:

  • 创建一个新的 browserHistory 将不起作用,因为 <BrowserRouter> 创建它自己的历史实例,并监听它的变化。因此,不同的实例将更改 url 但不会更新 <BrowserRouter>
  • browserHistory 在 v4 中没有被 react-router 暴露,仅在 v2 中暴露。

相反,您有几个选项可以执行此操作:

  • ### 使用 withRouter 高阶组件

相反,您应该使用 withRouter 高阶组件,并将其包装到将推送到历史记录的组件。例如:

   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);

查看 官方文档 以获取更多信息:

您可以通过组件路由器访问 history 对象的属性和最接近的 <Route>match 更高阶。 withRouter 将在每次使用与 <Route> render props: { match, location, history } 相同的道具时重新渲染其组件。


  • ### 使用 context API

使用上下文可能是最简单的解决方案之一,但作为一个实验性 API,它不稳定且不受支持。只有在其他一切都失败时才使用它。这是一个例子:

   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");
    }
    ...
  }

查看有关上下文的 官方文档

如果您希望您的应用程序稳定,请不要使用上下文。它是一个实验性的 API,很可能会在 React 的未来版本中被破坏。

如果尽管有这些警告你仍然坚持使用 context,请尝试将你对 context 的使用隔离到一个小区域,并尽可能避免直接使用 context API,以便在 API 更改时更容易升级。

原文由 Chris 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题