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

I am trying to route programmatically using this.props.history.push(..) , but it does not work.

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> 

CustomerList displays a list of customers. Clicking on the client (li) should make the application route to the client:

 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 fully illustrates the situation. It happens that the address bar of the browser changes according to history.push (..), but the view is not updated, the Customer component is not displayed, and the CustomerList still exists. Any ideas?

+25
source share
11 answers

Therefore, I came to this question in the hope of getting an answer, but to no avail. I used

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

In the same project, everything worked as expected. After further experiments and some comparisons and contrasts, I realized that this code will not work if it is called inside a nested component . Therefore, only the component of the rendered page can call this function for proper operation.

Find a working sandbox here

  • story: v4.7.2
  • respond: v16.0.0
  • React House: v16.0.0
  • response-router-dom: v4.2.2
+14
source

It seems that in the latest version of the react router, the situation has changed a bit. Now you can access the story through context. this.context.history.push('/path')

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

+11
source

You can try downloading a child component with a story. To do this, pass the "story" through the props. Something like that:

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

It seems like an old question, but still relevant.

I think this is a blocked update issue.

The main problem is that the new URL (route) must be displayed by the same component ( Costumers ) that is currently in use (current URL).

Thus, the solution is quite simple, make the URL of the window as a props, so that the reaction has a chance to detect a change in props (and therefore a change in URL), and act accordingly.

A good use case described in the official reaction blog is called " Recommendation: a completely uncontrolled component with a key . "

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

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

Thus, whenever the location changes in the reacting router, the component is removed (by reaction), and a new one is initiated with the correct values ​​(by reaction).

Yes, and pass location as a requisite to the component ( Costumers ) where the redirection will occur, if it has not yet been transferred.

Hope this helps someone.

+3
source

For me (reaction-router v4, react v16) the problem was that I had the navigation component in order:

 import { Link, withRouter } from 'react-router-dom' class MainMenu extends Component { render() { return ( ... <NavLink to="/contact">Contact</NavLink> ... ); } } export default withRouter(MainMenu); 

Both use either

 to="/contact" 

or

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

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

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

 // 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> 
+3
source

Do not use with a 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.

0
source

You need to export the client component, not the CustomerList .

  CustomersList = withRouter(Customers); export default CustomersList; 
0
source

You can access the properties of the history object and the closest match using the higher-order component withRouter . withRouter will pass updated matches, location, and history to the packaged component whenever it is rendered.

 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) 
0
source

Let's look at this scenario. You have App.jsx as the root file for ReactJS SPA. In this, your render() looks something like this:

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

then you can use this.props.history inside MyComponent without any problems. MySecondComponent say you render MySecondComponent inside MyComponent , in which case you need to call it like this:

 <MySecondComponent {...props} /> 

which will pass the props from MyComponent to MySecondComponent , thereby making this.props.history available in MySecondComponent

0
source

You need to bind handleCustomerClick :

 class Customers extends Component { constructor() { super(); this.handleCustomerClick = this.handleCustomerClick(this) } 
-3
source
 this.props.history.push('/customers/${customer.id}', null); 
-3
source

Source: https://habr.com/ru/post/1268444/


All Articles