1

I'm very new to React and first time time trying to implement navigation to a new page by pushing it to the history but am stuck on this error Cannot read property 'push' of undefined for react use history for a couple of hours now and think I need some help or guidance please.

Here are my small mvp components (I'm using Hooks):

import React, {useEffect, useState} from 'react';
import {BrowserRouter as Router, Route, Switch, useHistory} from "react-router-dom";
import Report from "./components/Report";

function App() {

let history = useHistory();

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

return (
    <Router>
        <Route path="/report" component={Report}/>
        <div>
            <button onClick={handleClick}>Click me</button>
        </div>

    </Router>
);
}

export default App

And

import React from "react";
import {withRouter} from "react-router-dom";

const Report = () => {

return (
    <div>Hello from report</div>
);

}

export default withRouter(Report)

Thank you very much.

Update

codesandbox.io/s/crazy-hill-1i6gb
I've added my complete code on the above link. The url now changes and no longer get the undefined error as per @Abir answer but the click me button still shows up rather than the text for the Report component.

Francislainy Campos
  • 1,743
  • 11
  • 36
  • Does this answer your question? [Uncaught TypeError: Cannot read property 'push' of undefined (React-Router-Dom)](https://stackoverflow.com/questions/44009618/uncaught-typeerror-cannot-read-property-push-of-undefined-react-router-dom) – izik Sep 06 '20 at 07:52
  • Hi, thank you for the quick reply. I've actually gone through quite a few questions and answers at this moment and this one too. It seems to be asking me to use withRouter on the component I'm trying to navigate to but I have that so not sure what else I could be missing. – Francislainy Campos Sep 06 '20 at 07:54
  • Can you share the codesandbox link? It will be easier to debug and understand root problem. – sidverma Sep 06 '20 at 07:56
  • Hi, these two classes are everything I have. – Francislainy Campos Sep 06 '20 at 07:57
  • 1
    The problem here is to use hook `useHistory` outside of the ``, to fix this you just simply move them all in a component of a `` – tmhao2005 Sep 06 '20 at 07:58

2 Answers2

8

The issue is because your Router component is nested inside of your App component rather than your App being nested inside of your router. The router acts as sort of a context provider and without your app being nested in the router the useHistory() hook has no provider to get the History from.

You can try something like this:

import React, {useEffect, useState} from 'react';
import {BrowserRouter as Router, Route, Switch, useHistory} from "react-router-dom";
import Report from "./components/Report";

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

    function handleClick() {
        history.push("/report");
    }
    
    return (
        <div>
            <button onClick={handleClick}>Click me</button>
        </div>
    )

}

function App() {

    return (
        <Router>
            <Route path="/report" component={Report}/>
            <Content />
        </Router>
    );
}

export default App

Abir Taheer
  • 1,091
  • 4
  • 16
0

As per the comments under the accepted answer here is the full gist of what worked to solve the issue.

import React from "react";
import { BrowserRouter as Router, Route, useHistory } from "react-router-dom";
import Report from "./components/Report";

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

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

return (
 <div>
    <button onClick={handleClick}>Click me</button>
 </div>
 );
}

function App() {
return (
 <Router>
   <Route path="/report" exact component={Report} />
   <Route path="/" exact component={Content} />
 </Router>
);
}

export default App;

And

import React from "react";

const Report = () => {
return <div>Hello from report</div>;
};

export default Report;
Francislainy Campos
  • 1,743
  • 11
  • 36
  • One thing I'd like to add is that you don't need to wrap your Report component export using `withRouter`. The reason being that you're not doing anything inside of the Report component that requires receiving the router as a property. – Abir Taheer Sep 06 '20 at 09:30
  • Cool, thank you for highlighting that. – Francislainy Campos Sep 06 '20 at 11:12