Cannot read property 'push' of undefined for react use history

Viewed 13224

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.

2 Answers

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

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;
Related