Javascript React-router v4 this.props.history.push(...) 不工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44312437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:26:29  来源:igfitidea点击:

React-router v4 this.props.history.push(...) not working

javascriptreactjsreact-reduxreact-router

提问by Andrea Ongaro

I'm trying to route programatically using this.props.history.push(..)but it doesn't seem to work.

我正在尝试以编程方式使用路由,this.props.history.push(..)但它似乎不起作用。

Here's the router:

这是路由器:

import {
 BrowserRouter as Router,
 Route
} from 'react-router-dom';

<Router>
 <Route path="/customers/" exact component={CustomersList} />
 <Route path="/customers/:id" exact component="{Customer} />
</Router>

In CustomerList, a list of customers is rendered. Clicking on a customer (li) should make the application route to Customer:

在 CustomerList 中,呈现客户列表。单击客户 (li) 应该使应用程序路由到客户:

import { withRouter } from 'react-router'

class Customers extends Component {
  static propTypes = {
    history: PropTypes.object.isRequired
  }

 handleCustomerClick(customer) {
   this.props.history.push(`/customers/${customer.id}`);
 }

 render() {
   return(
    <ul>
      { this.props.customers.map((c) =>
        <li onClick={() => this.handleCustomerClick(c)} key={c.id}>
          {c.name}
        </li> 
    </ul>
  )

 }
}

//connect to redux to get customers

CustomersList = withRouter(CustomersList);
export default CustomersList;

The code is partial but illustrates perfectly the situation. What happens is that the browser's address bar changes accordingly to history.push(..), but the view does not update, Customer component is not rendered and CustomersList is still there. Any ideas?

代码是部分的,但完美地说明了情况。发生的情况是浏览器的地址栏会根据 history.push(..) 进行相应更改,但视图并未更新,客户组件未呈现且客户列表仍在那里。有任何想法吗?

回答by Delanyo Aborchie

So I came to this question hoping for an answer but to no avail. I have used

所以我来到这个问题希望得到答案,但无济于事。我用过了

const { history } = this.props;
history.push("/thePath")

In the same project and it worked as expected. Upon further experimentation and some comparing and contrasting, I realized that this code will not run if it is called within the nested component. Therefore only the rendered page component can call this function for it to work properly.

在同一个项目中,它按预期工作。经过进一步的实验和一些比较和对比,我意识到如果在嵌套组件中调用此代码将无法运行。因此只有渲染的页面组件才能调用此函数使其正常工作。

Find Working Sandbox here

在此处查找工作沙盒

  • history: v4.7.2
  • react: v16.0.0
  • react-dom: v16.0.0
  • react-router-dom: v4.2.2
  • 历史:v4.7.2
  • 反应:v16.0.0
  • 反应域:v16.0.0
  • react-router-dom: v4.2.2

回答by cgat

It seems things have changed around a bit in the latest version of react router. You can now access history via the context. this.context.history.push('/path')

在最新版本的反应路由器中,事情似乎发生了一些变化。您现在可以通过上下文访问历史记录。this.context.history.push('/path')

Also see the replies to the this github issue: https://github.com/ReactTraining/react-router/issues/4059

另请参阅对此 github 问题的回复:https: //github.com/ReactTraining/react-router/issues/4059

回答by Taha A.

You can try to load the child component with history. to do so, pass 'history' through props. Something like that:

您可以尝试加载具有历史记录的子组件。为此,请通过道具传递“历史”。类似的东西:

  return (
  <div>
    <Login history={this.props.history} />
    <br/>
    <Register/>
  </div>
)

回答by Jan Matousek

For me (react-router v4, react v16) the problem was that I had the navigation component all right:

对我来说(react-router v4,react v16)问题是我的导航组件没问题:

import { Link, withRouter } from 'react-router-dom'

class MainMenu extends Component {

  render() {
    return (
            ...
            <NavLink to="/contact">Contact</NavLink>
            ...
    );
  }
}

export default withRouter(MainMenu);

Both using either

两者都使用

to="/contact" 

or

或者

OnClick={() => this.props.history.push('/contact')}; 

The behavior was still the same - the URL in browser changed but wrong components were rendered, the router was called with the same old URL.

行为仍然相同 - 浏览器中的 URL 已更改,但呈现了错误的组件,使用相同的旧 URL 调用路由器。

The culprit was in the router definition. I had to move the MainMenu component as a child of the Router component!

罪魁祸首是路由器定义。我不得不将 MainMenu 组件作为 Router 组件的子组件移动!

// wrong placement of the component that calls the router
<MainMenu history={this.props.history} />
<Router>
   <div>
     // this is the right place for the component!
     <MainMenu history={this.props.history} />
     <Route path="/" exact component={MainPage} />
     <Route path="/contact/" component={MainPage} />
   </div>
</Router>

回答by arcol

Seems like an old question but still relevant.

似乎是一个老问题,但仍然相关。

I think it is a blocked updateissue.

我认为这是一个阻止更新的问题。

The main problem is the new URL (route) is supposed to be rendered by the same component(Costumers) as you are currently in (current URL).

主要问题是新 URL(路由)应该由与Costumers您当前所在(当前 URL)相同的组件()呈现。

So solution is rather simple, make the window url as a prop, so react has a chance to detect the prop change (therefore the url change), and act accordingly.

所以解决办法很简单,把window url作为一个prop,这样react就有机会检测到prop的变化(因此url变化),并采取相应的行动。

A nice usecase described in the official react blog called Recommendation: Fully uncontrolled component with a key.

官方 React 博客中描述的一个很好的用例,名为“推荐:完全不受控制的组件,带有一个键”

So the solution is to change from render() { return( <ul>

所以解决方案是从 render() { return( <ul>

to render() { return( <ul key={this.props.location.pathname}>

render() { return( <ul key={this.props.location.pathname}>

So whenever the location changed by react-router, the component got scrapped (by react) and a new one gets initiated with the right values (by react).

因此,每当 react-router 更改位置时,组件就会报废(通过反应),并且会以正确的值(通过反应)启动一个新的组件。

Oh, and pass the locationas prop to the component(Costumers) where the redirect will happen if it is not passed already.

哦,然后将locationas 属性传递给 component( Costumers) ,如果尚未传递,将在该组件中发生重定向。

Hope it helps someone.

希望它可以帮助某人。

回答by Hemant

You can get access to the history object's properties and the closest 's match via the withRouterhigher-order component. withRouterwill pass updated match, location, and history props to the wrapped component whenever it renders.

您可以通过withRouter高阶组件访问历史对象的属性和最接近的匹配项。withRouter将在渲染时将更新的匹配、位置和历史道具传递给包装的组件。

import React, { Component } from 'react'
import { withRouter } from 'react-router'; 
// you can also import "withRouter" from 'react-router-dom';

class Example extends Component {
    render() {
        const { match, location, history } = this.props
        return (
            <div>
                <div>You are now at {location.pathname}</div>
                <button onClick={() => history.push('/')}>{'Home'}</button>
            </div>
        )
    }
}


export default withRouter(Example)

回答by SimantoR

Let's consider this scenario. You have App.jsxas the root file for you ReactJS SPA. In it your render()looks similar to this:

让我们考虑一下这种情况。您拥有App.jsxReactJS SPA 的根文件。在其中,您的render()外观类似于:

<Switch>
    <Route path="/comp" component={MyComponent} />
</Switch>

then, you should be able to use this.props.historyinside MyComponentwithout a problem. Let's say you are rendering MySecondComponentinside MyComponent, in that case you need to call it in such manner:

然后,您应该可以毫无问题地使用this.props.historyinside MyComponent。假设您正在渲染MySecondComponentinside MyComponent,在这种情况下,您需要以这种方式调用它:

<MySecondComponent {...props} />

which will pass the props from MyComponentdown to MySecondComponent, thus making this.props.historyavailable in MySecondComponent

这会将道具从MyComponent下传递到MySecondComponent,从而this.props.historyMySecondComponent

回答by Madacol

I had similar symptoms, but my problem was that I was nesting BrowserRouter

我有类似的症状,但我的问题是我在筑巢 BrowserRouter



Do not nest BrowserRouter, because the historyobject will refer to the nearest BrowserRouterparent. So when you do a history.push(targeturl)and that targeturlit's not in that particular BrowserRouterit won't match any of it's route, so it will not load any sub-component.

不要嵌套BrowserRouter,因为history对象将引用最近的BrowserRouter父对象。因此,当您执行 ahistory.push(targeturl)和那个targeturl 时,它不在那个特定的位置,BrowserRouter它不会匹配它的任何路由,因此它不会加载任何子组件。

Solution

解决方案

Nest the Switchwithout wrapping it with a BrowserRouter

嵌套而Switch不用BrowserRouter



Example

例子

Let's consider this App.jsfile

让我们考虑这个App.js文件

<BrowserRouter>
  <Switch>
    <Route exact path="/nestedrouter" component={NestedRouter}  />
    <Route exact path="/target" component={Target}  />
  </Switch>
</BrowserRouter>

Instead of doing this in the NestedRouter.jsfile

而不是在NestedRouter.js文件中执行此操作

<BrowserRouter>
  <Switch>
    <Route exact path="/nestedrouter/" component={NestedRouter}  />
    <Route exact path="/nestedrouter/subroute" component={SubRoute}  />
  </Switch>
</BrowserRouter>

Simply remove the BrowserRouterfrom NestedRouter.jsfile

只需BrowserRouterNestedRouter.js文件中删除

  <Switch>
    <Route exact path="/nestedrouter/" component={NestedRouter}  />
    <Route exact path="/nestedrouter/subroute" component={SubRoute}  />
  </Switch>

回答by Sandeep Kunaparaju

You need to export the CustomersComponent not the CustomerList.

您需要导出客户组件而不是CustomerList

    CustomersList = withRouter(Customers);
    export default CustomersList;

回答by YangFang

Don't use with Router.

不要与路由器一起使用。

handleSubmit(e){
   e.preventDefault();
   this.props.form.validateFieldsAndScroll((err,values)=>{
      if(!err){
        this.setState({
            visible:false
        });
        this.props.form.resetFields();
        console.log(values.username);
        const path = '/list/';
        this.props.history.push(path);
      }
   })
}

It works well.

它运作良好。