17

I have tried all the suggested ways in other threads and it is still not working which is why I am posting the question.

So I have history.js looking like this

import { createBrowserHistory } from 'history';

export default createBrowserHistory;

My index.js

render((
        <Router history={history}>
            <div>
                <Route component={App}/>
            </div>
        </Router>
    ), document.getElementById('root')
);

Home.js Looks like this

class Home extends Component {
    handleSubmit(e) {
        e.preventDefault();

        let teacherName = e.target.elements[0].value;
        let teacherTopic = e.target.elements[1].value;
        let path = `/featured/${teacherName}/${teacherTopic}`;
        history.push(path);

    }

    render() {
        return (
            <div className="main-content home">
                <hr />
                <h3>Featured Teachers</h3>
                <form onSubmit={this.handleSubmit}>
                    <input type="text" placeholder="Name"/>
                    <input type="text" placeholder="Topic"/>
                    <button type="submit"> Submit </button>
                </form>
            </div>
        );
    }
}

export default Home;

Home.js is actually routed in app.js which is routed in index.js.

The problem is that I cannot access history object anywhere.

The ways I have tried are as below

1) this.context.history.push(path) in home.js - cannot access context of undefined

2) this.props.history.push(path) in home.js - cannot access props of undefined

3) browserHistory.push(path) in index.js - this is deprecated now

4) the way above - _history2.default.push is not a function

None of the methods that I have tried above works. The second was the strangest as I should be able to access history object as props anywhere according to the documentation https://reacttraining.com/react-router/web/api/Route/Route-render-methods

I know the previous v2 or v3 way of accessing history is also deprecated.

So can someone who knows how to access history object in React Router v4 answer this question? Thanks.

forJ
  • 4,309
  • 6
  • 34
  • 60

3 Answers3

34

Looks to me like you might be missing a withRouter connection. this would make the history props available to this component

...

import { withRouter } from 'react-router'

class Home extends Component {
  functionMethod() {
    const { history: { push } } = this.props;
    doStuff();
    push('/location');
  }
  ...
}

export default withRouter(Home);

https://reacttraining.com/react-router/web/api/withRouter

Thomas Ingalls
  • 618
  • 10
  • 13
  • I get `cannot read property props of null`. No matter what I do it seems like I am not able to access the props – forJ Mar 30 '17 at 06:58
  • props is not in `this`? that sounds like you didn't successfully scope your function. try `onSubmit={e => this.handleSubmit(e)}` or binding handleSubmit in the constructor – Thomas Ingalls Mar 30 '17 at 07:10
  • oh that solution worked. but why? `this.handleSubmit` should refer to the same method in the instance shouldn't it? I am pretty sure that it works just by `this.handleSubmit` in react router v3. Can you please explain to me? thanks – forJ Mar 30 '17 at 07:30
  • The value of `this` depends a lot on how the function is *called*. When you pass your method as a reference as in `onSubmit={this.handleSubmit}`, React will later instantiate the class, and that instance will invoke the function in a context, but not the same context as where you defined the class. Check this out: http://jsbin.com/xayujimosa/1/edit?js,console – Thomas Ingalls Mar 30 '17 at 08:02
  • Oh okay so if you go `this.handleSubmit` it will be instantiated when the button is clicked; however, if you have an arrow function in there, it instantiates it when the component is rendered? – forJ Mar 30 '17 at 08:52
  • 1
    Yeah. More precisely, 'it will be instantiated' could be 'the `this` context will be defined' . – Thomas Ingalls Mar 30 '17 at 09:00
10

use the hook: useHistory

import { useHistory } from "react-router-dom";

function HomeButton() {
  let history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
Luhn
  • 706
  • 6
  • 15
0

I had this problem for a while and it was simply not having the withRouter connection.

import { withRouter } from 'react-router';


class Sample extends Component{

  render()
  {

     <button type="button" onClick={()=>{
                                this.props.history.push('/');
                                window.location.reload();    }}>
  }
}

export default withRouter(Sample);

`

D.Yash
  • 41
  • 2