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?
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
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
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>
)
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.
Seems like an old question but still relevant.
I think it is a blocked update issue.
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).
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.
A nice usecase described in the official react blog called Recommendation: Fully uncontrolled component with a key.
So the solution is to change from
render() {
return(
<ul>
to
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).
Oh, and pass the location
as prop to the component(Costumers
) where the redirect will happen if it is not passed already.
Hope it helps someone.
You need to bind handleCustomerClick
:
class Customers extends Component {
constructor() {
super();
this.handleCustomerClick = this.handleCustomerClick(this)
}
this.props.history.push(`/customers/${customer.id}`, null);