在当前版本的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.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为空以匹配路径。

其他回答

第一步在路由器中包装你的应用程序

import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));

现在我的整个应用程序都可以访问BrowserRouter。第二步,我导入Route,然后传递这些道具。可能在你的一个主文件里。

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

//lots of code here

//somewhere in my render function

    <Route
      exact
      path="/" //put what your file path is here
      render={props => (
      <div>
        <NameOfComponent
          {...props} //this will pass down your match, history, location objects
        />
      </div>
      )}
    />

现在如果我在我的组件js文件中运行console.log(this.props),我应该得到类似这样的东西

{match: {…}, location: {…}, history: {…}, //other stuff }

步骤2访问历史记录对象,修改位置

//lots of code here relating to my whatever request I just ran delete, put so on

this.props.history.push("/") // then put in whatever url you want to go to

另外,我只是一个编程训练营的学生,所以我不是专家,但我知道你也可以使用

window.location = "/" //wherever you want to go

如果我错了,请纠正我,但当我测试出来的时候,它重新加载了整个页面,我认为这击败了使用React的整个意义。

由于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>
)
}

我可以通过使用bind()来实现这一点。我想点击索引中的一个按钮。Jsx,向服务器发布一些数据,评估响应,并重定向到success.jsx。以下是我的计算方法……

index.jsx:

import React, { Component } from "react"
import { postData } from "../../scripts/request"

class Main extends Component {
    constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this)
        this.postData = postData.bind(this)
    }

    handleClick() {
        const data = {
            "first_name": "Test",
            "last_name": "Guy",
            "email": "test@test.com"
        }

        this.postData("person", data)
    }

    render() {
        return (
            <div className="Main">
                <button onClick={this.handleClick}>Test Post</button>
            </div>
        )
    }
}

export default Main

request.js:

import { post } from "./fetch"

export const postData = function(url, data) {
    // post is a fetch() in another script...
    post(url, data)
        .then((result) => {
            if (result.status === "ok") {
                this.props.history.push("/success")
            }
        })
}

success.jsx:

import React from "react"

const Success = () => {
    return (
        <div className="Success">
            Hey cool, got it.
        </div>
    )
}

export default Success

通过在index中绑定这个到postData。jsx,我能够访问this.props.history在request.js…那么我就可以在不同的组件中重用这个函数,只是要确保我记得包含这个。构造函数()中的postData = postData.bind(this)。

所以我的做法是: -而不是使用历史重定向。推送,我只是使用从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}/>
  }
}

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