在当前版本的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-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路由器V4现在允许历史道具如下所示:

this.props.history.push("/dummy",value)

然后,只要位置道具可用,就可以访问该值 State:{value}不是组件状态。

这是我的hack(这是我的根级文件,其中混合了一些redux -尽管我没有使用react-router-redux):

const store = configureStore()
const customHistory = createBrowserHistory({
  basename: config.urlBasename || ''
})

ReactDOM.render(
  <Provider store={store}>
    <Router history={customHistory}>
      <Route component={({history}) => {
        window.appHistory = history
        return (
          <App />
        )
      }}/>
    </Router>
  </Provider>,
  document.getElementById('root')
)

然后,我可以在任何我想要的地方使用window.appHistory.push()(例如,在我的redux商店函数/ thacks /sagas等),我希望我可以只使用window.customHistory.push(),但出于某种原因,react-router似乎从未更新,即使url发生了变化。但是这样我就有了react-router使用的EXACT实例。我不喜欢把东西放在全球范围内,这是我做过的为数不多的事情之一。但在我看来,这比我见过的任何其他选择都要好。

使用回调。这对我很管用!

export function addProduct(props, callback) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
    .then(response => {
    dispatch({ type: types.AUTH_USER });
    localStorage.setItem('token', response.data.token);
    callback();
  });
}

在组件中,你只需要添加回调

this.props.addProduct(props, () => this.props.history.push('/cart'))

所以我的做法是: -而不是使用历史重定向。推送,我只是使用从react-router-dom重定向组件 当使用这个组件时,你只需要传递push=true,它就会处理剩下的事情

import * as React from 'react';
import { Redirect } from 'react-router-dom';
class Example extends React.Component {
  componentDidMount() {
    this.setState({
      redirectTo: '/test/path'
    });
  }

  render() {
    const { redirectTo } = this.state;

    return <Redirect to={{pathname: redirectTo}} push={true}/>
  }
}

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

我有一个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调用之后推送到新的操作。

希望能有所帮助!