React-router v4 this.props.history.push(...) not working
Solution 1
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
Solution 2
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')
Also see the replies to the this github issue: https://github.com/ReactTraining/react-router/issues/4059
Solution 3
For me (react-router v4, react v16) the problem was that I had the navigation component all right:
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.
The culprit was in the router definition. I had to move the MainMenu component as a child 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>
Solution 4
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>
)
Solution 5
You can get access to the history object's properties and the closest 's match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
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)
Admin
Updated on December 31, 2021Comments
-
Admin over 2 years
I'm trying to route programatically using
this.props.history.push(..)
but it doesn't seem to 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>
In CustomerList, a list of customers is rendered. Clicking on a customer (li) should make the application route to Customer:
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?
-
cgat over 6 yearsA better way to do this is to use
withRouter
HOC. github.com/ReactTraining/react-router/blob/master/packages/… -
Adam Barnes about 6 years
-
anothernode almost 6 yearsWelcome to Stack Overflow! It would be great if you could add a little bit of an explanation about why you think this call solves the problem asked about in the question.
-
Hashan Seneviratne almost 6 yearsthis.handleCustomerClick = this.handleCustomerClick.bind(this) did the trick for me.
-
SuperUberDuper about 5 yearsI get history.push( is not a function
-
Subdigger over 3 yearsIMHO this is the same as this.pros.history.pus(). You just put it into other variable. both undefined to me....
-
Subdigger over 3 yearslooks like this is the way... and it is very sad