注释从这开始~
总览
导致"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 NPMnpm install react@latest react-dom@latest# ️ ONLY If you use TypeScriptnpm install --save-dev @types/react@latest @types/react-dom@latest# ----------------------------------------------# ️ with YARNyarn add react@latest react-dom@latest# ️ ONLY If you use TypeScriptyarn 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.jsonrm -rf node_modulesrm -f package-lock.json# ️ clean npm cachenpm cache clean --forcenpm install
如果谬误依然存在,请确保重启了IDE和开发服务。VSCode经常出现故障,须要重启。
调用组件
这里有另一个示例,用来展现谬误是如何产生的。
// App.jsimport {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 Hooks3. 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.jsimport {useState, useEffect} from 'react';// ️ not a component nor custom hook// so it can't use hooksfunction 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