使用useHistory

时间:2020-05-11 05:54:52

标签: reactjs react-router react-hooks

在我自己的代码上,我尝试通过将react-router的useHistory添加到导入中来>:

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

,然后在我的App()函数中定义一个变量:

let history = useHistory();

当我这样做时,我得到了错误:

TypeError: useContext(...) is undefined

来自react-router的hooks.js,具体行为:

return useContext(Context).history;

整个文件如下:

import React from "react";
import invariant from "tiny-invariant";

import Context from "./RouterContext.js";
import matchPath from "./matchPath.js";

const useContext = React.useContext;

export function useHistory() {
  if (__DEV__) {
    invariant(
      typeof useContext === "function",
      "You must use React >= 16.8 in order to use useHistory()"
    );
  }

  return useContext(Context).history;
}

export function useLocation() {
  if (__DEV__) {
    invariant(
      typeof useContext === "function",
      "You must use React >= 16.8 in order to use useLocation()"
    );
  }

  return useContext(Context).location;
}

export function useParams() {
  if (__DEV__) {
    invariant(
      typeof useContext === "function",
      "You must use React >= 16.8 in order to use useParams()"
    );
  }

  const match = useContext(Context).match;
  return match ? match.params : {};
}

export function useRouteMatch(path) {
  if (__DEV__) {
    invariant(
      typeof useContext === "function",
      "You must use React >= 16.8 in order to use useRouteMatch()"
    );
  }

  return path
    ? matchPath(useLocation().pathname, path)
    : useContext(Context).match;
}

更多背景信息:

enter image description here

我尝试用自己的代码访问React.useContext,它已定义并且是一个函数。

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

我认为您应该使用BrowserRouter(作为Router)将您的App封装在index.js中,然后在您的App中定义Switch和Routes。因为您不能在使用BrowserRouter的同一文件中使用useHistory或useLocation。 因此,请向上一级使用BrowserRouter包装器。

答案 1 :(得分:2)

发生这种情况是因为您需要将组件包装在 Router 元素中。例如:

import React from 'react';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
// import MyComponent

const history = createBrowserHistory();

const MyApp = ()=> (
  <Router {...{ history }}>
    <MyComponent />
  </Router>
);

export default MyApp;

答案 2 :(得分:0)

我遇到了useRouteMatch()的类似问题。我不确定原因是否相同。在测试中调用Cannot read property 'match' of undefined时,我从useContext(Context).match;行收到了错误useRouteMatch()


选项1:

无法定义useContext返回的方法之一是,如果提供给useContext的Context不包含任何数据。例如,如果您从https://codesandbox.io/s/react-hooks-usecontext-example-wv76d?file=/src/index.js:320-347中删除value={{ name: "Pupeno" }},则会看到类似的错误。

react-router-dom中可能存在类似的错误,当从这些挂钩中调用上下文时,该上下文可以为空。


选项2:

不看代码很难说。也可能像https://github.com/ReactTraining/react-router/issues/7332

答案 3 :(得分:0)

这个特定问题肯定不是这种情况,但也许有人最终会遇到和我一样的问题。

对我来说,解决方案是从 react-router-dom 而不是 react-router 包导入钩子。