解决React报错Invalid hook call

目录
  • 总览
  • 版本匹配
  • 调用组件

总览

导致"Invalid hook call. Hooks can only be called inside the body of a function component"错误的有多种原因:

  • reactreact-dom的版本不匹配。
  • 在一个项目中有多个react包版本。
  • 试图将一个组件作为一个函数来调用,例如,App()而不是<App />
  • 在类里面使用钩子,或者在不是组件或自定义钩子的函数中使用钩子。

版本匹配

在项目的根目录下打开终端,更新reactreact-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

翻译原文链接:bobbyhadz.com/blog/react-…

以上就是解决React报错Invalid hook call的详细内容,更多关于React报错Invalid hook call的资料请关注我们其它相关文章!

(0)

相关推荐

  • React实现一个倒计时hook组件实战示例

    目录 前言 思路 实现 总结 前言 本篇文章主要实现一个无样式的倒计时 hook 组件,通常不同地方的倒计时样式都不同,但倒计时的逻辑基本是都是一样的,因此可以抽离成一个工具方法或者一个 hook 组件,这样让倒计时逻辑可以进行通用,样式让业务方具体去实现. 思路 倒计时可能需要显示剩余时间的单位有:天.时.分.秒.毫秒,可能只需显示一个,也可能都需要显示. 注意细节: 只显示某一单位的时间或者需要显示的最大单元时间,需要可以大于正常时间最大限制,比如要剩余 100 小时 58 分时,小时需要可

  • React Hook Form 优雅处理表单使用指南

    目录 受控组件与非受控组件 受控组件 非受控组件 为什么需要非受控组件 React Hook Form 是什么? React Hook Form 的使用姿势 数据收集 表单嵌套 条件判断 表单列表 第三方组件 Typescript 支持 总结 受控组件与非受控组件 受控组件 先说说受控组件,以 input 为例: const [value,setValue] = useState('') <input value={value} onChange={(e)=> setValue(e.targe

  • React Hook 'useEffect' is called in function报错解决

    目录 总览 声明组件 声明自定义钩子 总结 总览 为了解决错误"React Hook 'useEffect' is called in function that is neither a React function component nor a custom React Hook function",可以将函数名的第一个字母大写,或者使用use作为函数名的前缀.比如说,useCounter使其成为一个组件或一个自定义钩子. 这里有个示例用来展示错误是如何发生的. // App.j

  • react hooks d3实现企查查股权穿透图结构图效果详解

    目录 前言 最终效果: 版本信息: 股权穿透图基础功能: 股权结构图基础功能: 股权穿透图代码 股权结构图代码 总结: 前言 umi+antd-admin 框架中使用hooks结合d3完成类似股权穿透图和股权结构图(web) 最终效果: 股权穿透图 股权结构图 版本信息: "d3": "4.13.0", "antd": "3.24.2", "umi": "^2.7.7", 股权穿透图基础

  • React hook 'useState' is called conditionally报错解决

    目录 总览 顶层调用 总览 当我们有条件地使用useState钩子时,或者在一个可能有返回值的条件之后,会产生"React hook 'useState' is called conditionally"错误.为了解决该错误,将所有React钩子移到任何可能油返回值的条件之上. 这里有个例子用来展示错误是如何发生的. import React, {useState} from 'react'; export default function App() { const [count,

  • React Hooks使用startTransition与useTransition教程示例

    目录 引言 需求分析 startTransition使用 useTransition 总结 引言 今天带来的是react18版本推出的全新hooks:useTransition,它的使用范围主要是用于性能优化,今天我们一探究竟吧. 需求分析 假设现在有如下需求:当用户在输入框查询数据时,需要实时根据用户输入数据进行搜索提示项的展示.与以往不同的是,提示列表的个数是十分庞大的,每次都在10000条以上. 设计过程 import {useState} from "react"; impor

  • 解决React报错React Hook useEffect has a missing dependency

    目录 总览 禁用规则 依赖移入 依赖移出 useMemo useCallback 总览 当useEffect钩子使用了一个我们没有包含在其依赖数组中的变量或函数时,会产生"React Hook useEffect has a missing dependency"警告.为了解决该错误,禁用某一行的eslint规则,或者将变量移动到useEffect钩子内. 这里有个示例用来展示警告是如何发生的. // App.js import React, {useEffect, useState}

  • 解决React报错Rendered more hooks than during the previous render

    目录 总览 顶层调用 条件之上 总览 当我们有条件地调用一个钩子或在所有钩子运行之前提前返回时,会产生"Rendered more hooks than during the previous render"错误.为了解决该错误,将所有的钩子移到函数组件的顶层,以及不要在条件中使用钩子. 这里有个示例用来展示错误是如何发生的. // App.js import {useEffect, useState} from 'react'; export default function App

  • 解决React报错useNavigate() may be used only in context of Router

    目录 总览 useNavigate Jest replace 总览 当我们尝试在react router的Router上下文外部使用useNavigate 钩子时,会产生"useNavigate() may be used only in the context of a Router component"警告.为了解决该问题,只在Router上下文中使用useNavigate 钩子. 下面是一个在index.js文件中将React应用包裹到Router中的例子. // index.j

  • 解决React报错Style prop value must be an object

    目录 总览 映射 提取 总览 在React中,当我们为元素的style 属性传递字符串时,会产生"Style prop value must be an object"警告.为了解决该警告,使用从属性到值的映射.比如说,style={{paddingLeft: '15px'}} . 这里有个例子来展示错误是如何发生的. // App.js const App = () => { // ️ Style prop value must be an object eslint(reac

  • 解决React报错The tag is unrecognized in this browser

    目录 总览 确保标签存在 小写字母开头 总览 当我们使用一个在浏览器中不存在的标签或以小写字母开头的组件名称时,会产生"The tag is unrecognized in this browser"React警告.为了解决该问题,只使用有效的标签名称,并将你的组件的第一个字母大写. 这里有个例子来展示错误是如何发生的. // App.js const App = () => { // ️ Warning: The tag <p1> is unrecognized i

  • 解决React报错Cannot assign to 'current' because it is a read-only property

    目录 总览 正确的泛型 DOM元素 总览 当我们用一个null值初始化一个ref,但在其类型中不包括null时,就会发生"Cannot assign to 'current' because it is a read-only property"错误.为了解决该错误,请在ref的类型中包含null.比如说,const ref = useRef<string | null>(null) . 这里有个例子来展示错误是如何发生的. // App.tsx import {useEf

  • 解决React报错Functions are not valid as a React child

    目录 总览 调用函数 总结 总览 产生"Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render."错误 通常是因为以下两个原因: 从render中返回一个函数引用而不是一个组件. 使用 react router 路由作为<Route path="/about" el

  • 解决React报错Unexpected default export of anonymous function

    目录 总览 命名 注释单行规则 总结 总览 当我们尝试使用默认导出来导出一个匿名函数时,会导致"Unexpected default export of anonymous function"警告.为了解决该错误,在导出函数之前,为函数赋予一个名称. 这里有个例子来展示警告是如何发生的. // Header.js // ️ default export for anonymous function // ️ Unexpected default export of anonymous

  • 解决React报错Expected an assignment or function call and instead saw an expression

    目录 正文 显式返回 隐式返回 返回对象 正文 当我们忘记从函数中返回值时,会产生"Expected an assignment or function call and instead saw an expression"错误.为了解决该错误,确保显式地使用return语句或使用箭头函数隐式返回. 下面有两个示例来展示错误是如何产生的. // App.js const App = props => { const result = ['a', 'b', 'c'].map(el

  • 解决React报错You provided a `checked` prop to a form field

    目录 总览 defaultChecked onChange 初始值 总览 当我们在多选框上设置了checked 属性,却没有onChange 处理函数时,会产生"You provided a checked prop to a form field without an onChange handler"错误.为了解决该错误,可以使用defaultChecked 属性,或者在表单字段上设置onChange 属性. 这里有个例子用来展示错误是如何发生的. // App.js export

随机推荐