11

I am using react router 4.0 version. I am trying to navigate from one component to another on button click. I have implemented react routing for this. After implementation when i click the navigate button it is giving me error "Uncaught TypeError: this.context.router.push is not a function" and a warning "Failed context type: Invalid context router of type object supplied to EmpLogin, expected function." Tried a lot but could not make it working. below are my component and routing implementation. Earlier i was using react router 2.0 and browserhistory.push was working.

export class EmpLogin extends React.Component {
  constructor(props) {
super(props);
this.state = {

};
}

loginID(e) {
this.setState({loginID: e.target.value});
}

 Password(e) {
this.setState({password: e.target.value});
}

 navigate(e){
    e.preventDefault();
    this.context.router.push('/EmpDetails');
  }

render() {
  return (
    <div>
    <div >
      <form>
        <input type="text" onChange={this.loginID.bind(this)} />
        <input type="password" onChange={this.Password.bind(this)} />  
        <div>
            {this.props.children}
            <button onClick={this.navigate.bind(this)}>feature</button>
        </div>
      </form>
    </div>
  </div>
);
 }
 }

  EmpLogin.contextTypes = {
  router: React.PropTypes.func.isRequired
 }

 export default EmpLogin;

Routing implementation -

import React from 'react';
import ReactDOM from 'react-dom';
import EmpLogin from './EmpLogin';
import {Router, Route,HashRouter} from 'react-router-dom';
import {browserHistory,hashHistory} from 'react-router';
import EmpDetails from './EmpDetails';

ReactDOM.render((
 <HashRouter>
 <div>
  <Route exact path='/' component={EmpLogin}/>
  <Route path='/Emplogin' component={EmpLogin}/>
  <Route path='/EmpDetails' component={EmpDetails} />
  </div>
  </HashRouter>
 ), document.getElementById('root'));
user2768132
  • 460
  • 4
  • 11
  • 26

4 Answers4

28

The correct way to navigate using context in react-router v4:

this.context.router.history.push('/EmpDetails')

The new react-router v4 has changed the location of the push method when accessing this.context.router. router now has history and route as properties and it is within history that you will find the allocated method.

Also, if you are using the latest react version 15.5.0, propTypes have been removed into a separate package and you can get them with:

npm install prop-types --save

or

yarn add prop-types

This is written for documentation reasons. Other users answers did not successfully solve the issue, and as I had this issue I decided to fill it in for the convenience of future developers.

halfer
  • 19,824
  • 17
  • 99
  • 186
hanorine
  • 7,256
  • 3
  • 14
  • 18
  • In case `this.context.router` is undefined (due to updates), you can find a more thorough discussion here: https://stackoverflow.com/questions/42701129/how-to-push-to-history-in-react-router-v4 – juanitogan Jul 18 '20 at 02:51
2

From the error it seems that it is looking for router as an object:

Try this:

EmpLogin.contextTypes = {
  router: React.PropTypes.object.isRequired
}

Also you can try transitionTo instead of push() along with the above method

this.context.router.transitionTo('/EmpDetails');
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
0

you should use browserHistory from react-router instead...

  browserHistory.push('/EmpDetails');
Jhim
  • 44
  • 8
  • try the suggestion on this... [link](https://github.com/chentsulin/electron-react-boilerplate/issues/808), you might be able to use react-router-dom since your on the 4.0.. – Jhim Apr 05 '17 at 09:43
0

I have mixed your answers. And then I have succeeded on react 16.5.2!

Install prop-types

npm i prop-types --save

Import PropTypes in my NavMenu.js

import PropTypes from 'prop-types';

Set contextTypes

NavMenu.contextTypes = {
  router: PropTypes.object.isRequired
};

Finally use this.context.router.history.push

<MenuItem onClick={handleClose}>
  <span onClick={() => this.context.router.history.push("/")}>
    Home
  </span>
</MenuItem>
kenjiuno
  • 341
  • 5
  • 11