问题
I am trying to programmatically change pages using browserHistory.push
. In one of my components, but not in a component that I embedded inside of that one.
Does anyone know why my project is throwing the error below only for the child component but not for the parent component?
Cannot read property 'push' of undefined
Parent Component
import React, {Component} from 'react';
import { browserHistory } from 'react-router';
import ChildView from './ChildView';
class ParentView extends Component {
constructor(props) {
super(props);
this.addEvent = this.addEvent.bind(this);
}
changePage() {
this.props.history.push("/someNewPage");
}
render() {
return (
<div>
<div>
<button onClick={this.changePage}>Go to a New Page!</button>
</div>
<ChildView /> // this is the child component where this.props.history.push doesn't work
</div>
);
}
}
function mapStateToProps(state) {
return {
user: state.user
};
}
function matchDispatchToProps(dispatch) {
return bindActionCreators({
setName: setName
}, dispatch)
}
export default connect(mapStateToProps, matchDispatchToProps)(ParentView);
Child Component
import React, {Component} from 'react';
import { browserHistory } from 'react-router';
class ChildView extends Component {
constructor(props) {
super(props);
this.addEvent = this.addEvent.bind(this);
}
changePage() {
this.props.history.push("/someNewPage");
}
render() {
return (
<div>
<div>
<button onClick={this.changePage}>Go to a New Page!</button>
</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
user: state.user
};
}
function matchDispatchToProps(dispatch) {
return bindActionCreators({
setName: setName
}, dispatch)
}
export default connect(mapStateToProps, matchDispatchToProps)(ChildView);
Router
// Libraries
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { browserHistory } from 'react-router';
// Components
import NotFound from './components/NotFound';
import ParentView from './components/ParentView';
import ChildView from './components/ChildView';
import SomeNewPage from './components/SomeNewPage';
// Redux
import { Provider } from 'react-redux';
import {createStore} from 'redux';
import allReducers from './reducers';
const store = createStore(
allReducers,
window.devToolsExtension && window.devToolsExtension()
);
const routes = (
<Router history={browserHistory}>
<div>
<Provider store={store}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/parentView" component={ParentView} />
<Route path="/someNewPage" component={SomeNewPage} />
<Route path="/childView" component={ChildView} />
<Route component={NotFound} />
</Switch>
</Provider>
</div>
</Router>
);
export default routes;
As you can see, the components are virtually exactly the same except that the child one is inside the parent one.
Note I have tried these approaches but they do not resolve the issue for me:
- Uncaught TypeError: Cannot read property 'push' of undefined with correct import being available
- React browserHistory.push giving Uncaught TypeError: Cannot read property 'push' of undefined
- redirect to a page programmatically in react-router 2
回答1:
You answered your question in your question.
As you can see, the components are virtually exactly the same except that the child one is inside the parent one.
The very fact that the component is nested one further is your issue. React router only injects the routing props to the component it routed to, but not to the components nested with in.
See the accepted answer to this question. The basic idea is that you now need to find a way to inject the routing props to the child component.
You can do that by wrapping the child in a HOC withRouter
.
export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView));
I hope this helps.
回答2:
Using withRouter is fine, an alternative option is to pass the history as a prop from parent to child (without using withRouter), e.g:
Parent
<SignupForm history={this.props.history}/>
Child
this.props.history.push('/dashboard');
回答3:
You Can try this
this.context.history.push('/dashboard')
or pass the history as a prop from parent to child component like
parent
<SignupForm history={this.props.history}/>
child
this.props.history.push('/dashboard');
or withRouter
import { withRouter } from "react-router";
export default withRouter(connect(mapStateToProps, {
...
})(Header));
回答4:
This is the problem of Nested Components. I was facing this issue in Header component. I wanted to redirect the page to home page on clicking the logo.
this.props.history.push
won't work in nested components.
So Solution is to use withRouter
.
To Use withRouter
just copy paste Below 2 lines in Header(You can use it in your component) :
import { withRouter } from "react-router";
export default withRouter(connect(mapStateToProps, {
...
})(Header));
回答5:
If anyone is still facing similar issues please try to change the onClick to this
onClick={() => this.props.history.push("/dashboard")}
also if you are in a child component please use the <Redirect to="/dashboard"/>
component
来源:https://stackoverflow.com/questions/43837212/this-props-history-push-works-in-some-components-and-not-others