Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

reactjs - Cannot read property 'history' of undefined (useHistory hook of React Router 5)

I am using the new useHistory hook of React Router, which came out a few weeks ago. My React-router version is 5.1.2. My React is at version 16.10.1. You can find my code at the bottom.

Yet when I import the new useHistory from react-router, I get this error:

Uncaught TypeError: Cannot read property 'history' of undefined

which is caused by this line in React-router

function useHistory() {
  if (process.env.NODE_ENV !== "production") {
    !(typeof useContext === "function") ? process.env.NODE_ENV !== "production" ? invariant(false, "You must use React >= 16.8 in order to use useHistory()") : invariant(false) : void 0;
  }

  return useContext(context).history; <---------------- ERROR IS ON THIS LINE !!!!!!!!!!!!!!!!!
}

Since it is related to useContext and perhaps a conflict with context is at fault, I tried completely removing all calls to useContext, creating the provider, etc. However, that did nothing. Tried with React v16.8; same thing. I have no idea what could be causing this, as every other feature of React router works fine.

***Note that the same thing happens when calling the other React router hooks, such as useLocation or useParams.

Has anyone else encountered this? Any ideas to what may cause this? Any help would be greatly appreciated, as I found nothing on the web related to this issue.

import React, {useEffect, useContext} from 'react';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Switch, useHistory } from 'react-router'
import { useTranslation } from 'react-i18next';

import lazyLoader from 'CommonApp/components/misc/lazyLoader';
import {AppContext} from 'CommonApp/context/context';

export default function App(props) {
    const { i18n } = useTranslation();
    const { language } = useContext(AppContext);
    let history = useHistory();

    useEffect(() => {
        i18n.changeLanguage(language);
    }, []);

    return(
        <Router>
            <Route path="/">
                <div className={testClass}>HEADER</div>
            </Route>
        </Router>
    )
}

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's because the react-router context isn't set in that component. Since its the <Router> component that sets the context you could use useHistory in a sub-component, but not in that one.

Here is a very basic strategy for solving this issue:

const AppWrapper = () => {
  return (
    <Router> // Set context
      <App /> // Now App has access to context
    </Router>
  )
}

const App = () => {
  let history = useHistory(); // Works!
...
// Render routes in this component

Then just be sure to use the "wrapper" component instead of App directly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...