在当前版本的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 5中已经包含了一个历史记录,因此我们可以通过参考访问相同的历史记录

import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';

function App() {
   const routerRef = React.useRef();
   const onProductNav = () => {
       const history = routerRef.current.history;
       history.push("product");
   }
return (
    <BrowserRouter ref={routerRef}>
        <Switch>
            <Route path="/product">
                <ProductComponent />
            </Route>
            <Route path="/">
                <HomeComponent />
            </Route>
        </Switch>
    </BrowserRouter>
)
}

其他回答

如果你正在使用Redux,那么我建议使用npm包react-router-redux。它允许您分派Redux存储导航操作。

你必须在他们的自述文件中创建存储。

最简单的用例:

import { push } from 'react-router-redux'

this.props.dispatch(push('/second page'));

容器/组件的第二个用例:

容器:

import { connect } from 'react-redux';
import { push } from 'react-router-redux';

import Form from '../components/Form';

const mapDispatchToProps = dispatch => ({
  changeUrl: url => dispatch(push(url)),
});

export default connect(null, mapDispatchToProps)(Form);

组件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Form extends Component {
  handleClick = () => {
    this.props.changeUrl('/secondPage');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}/>
      </div>Readme file
    );
  }
}

在这种情况下,你将道具传递给你的坦克。所以你可以简单地打电话

props.history.push('/cart')

如果情况并非如此,您仍然可以从组件传递历史记录

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}

同样的话题也困扰着我。 我使用react-router-dom 5, Redux 4和BrowserRouter。 我更喜欢基于功能的组件和钩子。

像这样定义组件

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

const Component = () => {
  ...
  const history = useHistory();
  dispatch(myActionCreator(otherValues, history));
};

你的动作创造者紧随其后

const myActionCreator = (otherValues, history) => async (dispatch) => {
  ...
  history.push("/path");
}

当然,如果不需要async,可以使用更简单的动作创建器

由于react router 5中已经包含了一个历史记录,因此我们可以通过参考访问相同的历史记录

import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';

function App() {
   const routerRef = React.useRef();
   const onProductNav = () => {
       const history = routerRef.current.history;
       history.push("product");
   }
return (
    <BrowserRouter ref={routerRef}>
        <Switch>
            <Route path="/product">
                <ProductComponent />
            </Route>
            <Route path="/">
                <HomeComponent />
            </Route>
        </Switch>
    </BrowserRouter>
)
}

根据React Router v4文档- Redux深度集成会话

深度整合需要:

“能够通过调度操作进行导航”

然而,他们推荐这种方法作为“深度集成”的替代方案:

“你可以将提供给路由组件的历史对象传递给你的操作,而不是分派操作来导航。”

所以你可以用withRouter高阶组件来包装你的组件:

export default withthrouter (connect(null, {actionCreatorName})(ReactComponent));

它将历史API传递给道具。你可以调用动作创建者传递历史作为参数。例如,在你的ReactComponent中:

onClick={() => {
  this.props.actionCreatorName(
    this.props.history,
    otherParams
  );
}}

然后,在actions/index.js中:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}