使用 useHistory、useLocation 挂钩的挂钩调用无效

Posted

技术标签:

【中文标题】使用 useHistory、useLocation 挂钩的挂钩调用无效【英文标题】:Invalid hook call for using useHistory, useLocation hooks 【发布时间】:2020-08-13 11:21:42 【问题描述】:

App.js:

import React from 'react';
import  Router, Route  from 'react-router-dom';
import Display from './Components/Display';

export function App() 
  return (
    <Router>
      <Route path="/" component=Display />
    </Router>
  );

Display.js

import React from 'react';
import  useLocation, useHistory  from 'react-router-dom';

function History() 
  let history = useHistory(); // error saying invalid hook call
  let location = useLocation();
  console.log(history);
  return <h2>Hello Display</h2>;


export default History;

我在使用这些钩子时面临无效的钩子调用。

这是我的依赖:

"dependencies": 
  "@testing-library/jest-dom": "^4.2.4",
  "@testing-library/react": "^9.3.2",
  "@testing-library/user-event": "^7.1.2",
  "axios": "^0.19.2",
  "react": "^16.13.1",
  "react-dom": "^16.13.1",
  "react-redux": "^7.2.0",
  "react-router": "^5.1.2",
  "react-scripts": "3.4.1",
  "redux": "^4.0.5"

【问题讨论】:

你的依赖中没有 react-router-dom 【参考方案1】:

很多“就我而言”的答案,就我而言,正如错误所说,不要在函数体之外调用钩子。所以,先实例化实例然后推送到历史:

import  useHistory  from 'react-router-dom';

const Hook = (props) => 
  // do not take it elsewhere
  const history = useHistory();

  return(
    <>
      component
      <button onClick=() => history.push('/path')> Button </button>
    </>)

【讨论】:

【参考方案2】:

就我而言,我通过在包 .json 中添加分辨率解决了这个问题

"resolutions": 
    "babel-loader": "8.1.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-router-dom": "5.3.0"

【讨论】:

【参考方案3】:

在我的例子中,我在事件处理程序中使用了 useHistory。

当我从事件处理程序中删除 let history = useHistory(); 行代码时,问题解决了。

在 ReactJs 中如何使用钩子有一些限制。

? 不要在类组件中调用 Hooks。

? 不要调用事件处理程序。

? 不要在传递给 useMemo、useReducer 或 useEffect 的函数内部调用 Hook。

更多,你可以阅读这个Invalid Hook Call Warning

【讨论】:

你使用的 react 和 react-router-dom 是什么版本 "react": "^17.0.1", "react-dom": "^17.0.1",【参考方案4】:

我在从 React 16 升级到 React 17 时遇到了完全相同的问题。这是由“React 和渲染器(例如 React DOM)的版本不匹配”引起的。我升级了所有依赖项,它开始工作。 以下依赖项列表对我有用。

"dependencies": 
  "@material-ui/core": "^4.9.10",
  "@material-ui/icons": "^4.9.1",
  "@material-ui/lab": "^4.0.0-alpha.50",
  "@testing-library/jest-dom": "^5.12.0",
  "@testing-library/react": "^11.2.6",
  "@testing-library/user-event": "^13.1.5",
  "formik": "^2.1.4",
  "loadjs": "^4.2.0",
  "lodash": "^4.17.15",
  "history": "^5.0.0",
  "prop-types": "^15.7.2",
  "pure-react-carousel": "^1.27.0",
  "react": "^17.0.2",
  "react-addons-css-transition-group": "^15.6.2",
  "react-dom": "^17.0.2",
  "react-render-html": "^0.6.0",
  "react-router-dom": "^5.2.0",
  "react-scripts": "^4.0.3",
  "web-vitals": "^1.0.1",
  "yup": "^0.28.3"

PS:我在多个 React 项目中使用“纱线工作区”。每个都有不同的依赖项列表。我必须分离一个项目才能使其工作并得出这个结论。

【讨论】:

react、react-router-dom 的版本和你的一样,但我还是遇到了这个问题。 我可以确认这些依赖项集有效。尝试检查您的项目中没有其他反应版本。同时删除“node_modules”和“package-lock.json”或“yarn.lock”并重新安装【参考方案5】:

在我的例子中,我使用的是 React Element 而不是 React Component,这就是 useHistory() 钩子抛出错误的原因。

【讨论】:

【参考方案6】:

我将我的 react 版本降级到 16.14.0,现在它可以工作了。 react 17.0 似乎被 react-router-dom 破坏了

【讨论】:

【参考方案7】:

您正在使用 react-router-dom 中的路由器组件,但未提供自定义历史对象。

您可以使用 BrowserRouter 或提供自定义历史道具

import React from 'react';
import  BrowserRouter as Router, Route from 'react-router-dom';
import Display from './Components/Display';

export  function App() 


  return (
    <Router>
        <Route path="/" component=Display  />
    <Router>
  )

显示.js

import React from 'react';
import  useLocation, useHistory  from 'react-router-dom'

function History() 
    let history = useHistory();
    let location = useLocation();
    console.log(history)
    return<h2>Hello Display</h2>


export default History

【讨论】:

我试过 BrowserRouter ,仍然面临同样的问题 你也没有调用定位函数。请检查 我也有同样的问题。使用 BrowserRouter 并没有解决问题。 @blankface 你有react v16.8 或以上版本以及react-router-dom v5.1 或以上版本 两者都是。我正在使用 create-react-app

以上是关于使用 useHistory、useLocation 挂钩的挂钩调用无效的主要内容,如果未能解决你的问题,请参考以下文章

“react-router-dom”中的 useLocation 返回意外对象

如何正确使用 react-router-dom 中的 useHistory()?

每个组件的 useHistory 默认值

模拟 useHistory 并期望 toBeCalledWith

如何在类组件类型脚本中使用 useHistory() 钩子

useLocation 在 GoogleChrome 中有效,但在 Firefox 中无效