共计 2188 个字符,预计需要花费 6 分钟才能阅读完成。
注释从这开始~
总览
导致 ”Invalid hook call. Hooks can only be called inside the body of a function component” 谬误的有多种起因:
react
和react-dom
的版本不匹配。- 在一个我的项目中有多个
react
包版本。 - 试图将一个组件作为一个函数来调用,例如,
App()
而不是<App />
。 - 在类外面应用钩子,或者在不是组件或自定义钩子的函数中应用钩子。
版本匹配
在我的项目的根目录下关上终端,更新 react
和react-dom
包的版本,确保版本是相匹配的,并且没有应用过期的版本。
# 👇️ with NPM | |
npm install react@latest react-dom@latest | |
# 👇️ ONLY If you use TypeScript | |
npm install --save-dev @types/react@latest @types/react-dom@latest | |
# ---------------------------------------------- | |
# 👇️ with YARN | |
yarn add react@latest react-dom@latest | |
# 👇️ ONLY If you use TypeScript | |
yarn add @types/react@latest @types/react-dom@latest --dev |
如果谬误仍存在,尝试删除 node_modules
以及package-lock.json
(不是package.json
)文件,从新运行npm install
并重启你的 IDE。
这个谬误通常是因为在同一个我的项目中领有多个版本的 react
造成的。
# 👇️ delete node_modules and package-lock.json | |
rm -rf node_modules | |
rm -f package-lock.json | |
# 👇️ clean npm cache | |
npm cache clean --force | |
npm install |
如果谬误依然存在,请确保重启了 IDE 和开发服务。VSCode 经常出现故障,须要重启。
调用组件
这里有另一个示例,用来展现谬误是如何产生的。
// App.js | |
import {useState} from 'react'; | |
// 👇️ Don't call components as functions 👇️ | |
App(); | |
export default function App() { | |
/** | |
* ⛔️ Warning: Invalid hook call. Hooks can only be | |
* called inside of the body of a function component. | |
* This could happen for one of the following reasons: | |
1. You might have mismatching versions of React and the renderer (such as React DOM) | |
2. You might be breaking the Rules of Hooks | |
3. You might have more than one copy of React in the same app | |
*/ | |
const [count, setCount] = useState(0); | |
return ( | |
<div> | |
<h1>Hello world</h1> | |
</div> | |
); | |
} |
问题在于,咱们将
App
组件作为函数进行调用。
你应该只应用具备 JSX 语法的组件。比方:<App country="Austria" age="30" />
,而不是App({country: 'Austria', age: 30})
。
确保你没有在一个类组件,或一个既不是组件也不是自定义钩子的函数外面调用钩子。
如果你有一个类,请将其转换为可能应用钩子的函数。
上面是一个例子,阐明在一个既不是组件也不是自定义钩子的函数中是如何引起谬误的。
// App.js | |
import {useState, useEffect} from 'react'; | |
// 👇️ not a component nor custom hook | |
// so it can't use hooks | |
function counter() {const [count, setCount] = useState(0); | |
useEffect(() => {console.log('hello world'); | |
}, []); | |
} |
counter
函数以小写的 c
结尾,所以它不被 React 认为是一个组件。因为所有的组件名称必须以大写字母结尾。它同样也不是自定义钩子,因为其名称没有以 use
结尾,比如说useCounter
。
咱们只能在函数组件或自定义钩子外面应用钩子,所以可能应用钩子的一个办法是将 counter
重命名为useCounter
。
import {useState, useEffect} from 'react'; | |
function useCounter() {const [count, setCount] = useState(0); | |
useEffect(() => {console.log('hello world'); | |
}, []); | |
} |
当初 React 认为 useCounter
是一个自定义钩子,并容许咱们在外面应用钩子。
就像文档中所说的那样:
- 只从 React 函数组件或自定义钩子中调用 Hook
- 只在最顶层应用 Hook
- 不要在循环,条件或嵌套函数中调用 Hook
- 确保总是在你的 React 函数的最顶层以及任何 return 之前应用 Hook