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() {
const [counter, setCounter] = useState(0);
// ️ Error: Rendered more hooks than during the previous render.
if (counter > 0) {
// ️ calling React hook conditionally
useEffect(() => {
console.log('hello world');
});
}
return (
<div>
<button onClick={() => setCounter(counter + 1)}>toggle loading</button>
<h1>Hello world</h1>
</div>
);
}
代码的问题在于,我们有条件地调用了useEffect钩子。
顶层调用
为了解决该错误,我们必须将条件移到钩子内部。因为React钩子只能在顶层调用。
import {useEffect, useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
// hook is called at top level (not conditionally)
useEffect(() => {
if (counter > 0) {
console.log('hello world');
}
});
return (
<div>
<button onClick={() => setCounter(counter + 1)}>toggle loading</button>
<h1>Hello world</h1>
</div>
);
}
我们将if语句移动到了useEffect钩子内部。
这就解决了错误,因为我们必须确保每次组件渲染时,React钩子都以相同的顺序被调用。
这意味着我们不允许在循环、条件或嵌套函数中使用钩子。
这里有另外一个示例用来展示错误是如何发生的。
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
// ️ this returns before second hook runs if condition is met
if (counter > 0) {
return <h2>Returning early</h2>;
}
// ️ Error because hook is called conditionally
const [color, setColor] = useState('salmon');
return (
<div>
<button onClick={() => setCounter(counter + 1)}>toggle loading</button>
<h1>Hello world</h1>
</div>
);
}
问题在于,第二个useState钩子只有在上面的条件没有满足时才会被调用。
条件之上
为了解决这个错误,把所有的钩子移到组件的顶层,在任何可能返回值的条件之上。
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
const [color, setColor] = useState('salmon');
// ️ condition that may return early must be below all hooks
if (counter > 0) {
return <h2>Returning early</h2>;
}
return (
<div>
<button onClick={() => setCounter(counter + 1)}>toggle loading</button>
<h1>Hello world</h1>
</div>
);
}
我们把第二个useState钩子移动到有可能返回一个值的if条件上面。
这是很有帮助的,因为钩子现在在顶层,并且有可预测的行为,允许React在调用
useState和useEffect之间正确地保存状态。
就像文档中所说的那样:
- 只从React函数组件或自定义钩子中调用Hook
- 只在最顶层使用 Hook
- 不要在循环,条件或嵌套函数中调用 Hook
- 确保总是在你的 React 函数的最顶层以及任何 return 之前使用 Hook
这有助于React在多个useState和useEffect调用之间保留钩子的状态。
React报错之Rendered more hooks than during the previous render的更多相关文章
- react 报错的堆栈处理
react报错 Warning: You cannot PUSH the same path using hash history 在Link上使用replace 原文地址https://reactt ...
- React报错 :browserHistory doesn't exist in react-router
由于版本问题,React中history不可用 import { hashHistory } from 'react-router' 首先应该导入react-router-dom包: import { ...
- react报错 TypeError: Cannot read property 'setState' of undefined
代码如下: class test extends Component { constructor(props) { super(props); this.state = { liked: false ...
- React报错之Cannot find name
正文从这开始~ .tsx扩展名 为了在React TypeScript中解决Cannot find name报错,我们需要在使用JSX文件时使用.tsx扩展名,在你的tsconfig.json文件中把 ...
- React报错之Cannot find namespace context
正文从这开始~ 总览 在React中,为了解决"Cannot find namespace context"错误,在你使用JSX的文件中使用.tsx扩展名,在你的tsconfig. ...
- React报错之Expected `onClick` listener to be a function
正文从这开始~ 总览 当我们为元素的onClick属性传递一个值,但是该值却不是函数时,会产生"Expected onClick listener to be a function" ...
- React报错:Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix,
今天在开发时报了以下错误,记录一下 我们不能在组件销毁后设置state,防止出现内存泄漏的情况 出现原因直接告诉你了,组件都被销毁了,还设置个锤子的state啊 解决方案: 利用生命周期钩子函数:co ...
- react报错this.setState is not a function
当报错这个的时候就要看函数是否在行内绑定this,或者在constructor中绑定this. 我这里犯的错误的是虽然我在constructor中绑定了this,但是语法写的不正确. 错误示范: co ...
- React报错之React hook 'useState' is called conditionally
正文从这开始~ 总览 当我们有条件地使用useState钩子时,或者在一个可能有返回值的条件之后,会产生"React hook 'useState' is called conditiona ...
随机推荐
- 对互斥事件和条件概率的相互理解《考研概率论学习之我见》 -by zobol
1.从条件概率来定义互斥和对立事件 2.互斥事件是独立事件吗? 3.每个样本点都可以看作是互斥事件,来重新看待条件概率 一.从条件概率来定义互斥和对立事件 根据古典概率-条件概率的定义,当在" ...
- JS:构造函数
定义:在JavaScript中,用new关键字来调用的函数,称为构造函数,构造函数首字母一般大写. 理解: 构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象. 创建对象, ...
- 领导:谁再用redis过期监听实现关闭订单,立马滚蛋!
日前拜读阿牛老师的大作 领导:谁再用定时任务实现关闭订单,立马滚蛋! 发现其方案有若干瑕疵,特此抛砖引玉讨论一二. 在电商.支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时 ...
- 「非软文」零基础学习TypeScript(源码开源)
今天,这篇文章篇幅很短,主要开放我最近学习整理TypeScript源码. 源码地址 https://github.com/maomincoding/typeScript_study 更多内容请见原文, ...
- Python selenium 实现大麦网自动购票过程
一些无关紧要的哔哔: 大麦网是中国综合类现场娱乐票务营销平台,业务覆盖演唱会. 话剧.音乐剧.体育赛事等领域今天,我们要用代码来实现他的购票过程 开搞! 先来看看完成后的效果是怎么样的 开发环境 版 ...
- UML图记忆技巧
什么是UML类图 Class Diagram:用于表示类.接口.实例等之间相互的静态关系 虽然名字叫类图,但类图中并不只有类 记忆技巧 UML箭头方向: 从子类指向父类 我相信 很多同学都会有和我一样 ...
- 全国气象数据/降雨量分布数据/太阳辐射数据/NPP净初级生产力数据/植被覆盖度数据
气象数据一直是一个价值较高的数据,它被广泛用于各个领域的研究当中.气象数据包括有气温.气压.相对湿度.降水.蒸发.风向风速.日照等多种指标,但是包含了这些全部指标的气象数据却较难获取 ...
- Modeling Conversation Structure and Temporal Dynamics for Jointly Predicting Rumor Stance and Veracity(ACL-19)
记录一下,论文建模对话结构和时序动态来联合预测谣言立场和真实性及其代码复现. 1 引言 之前的研究发现,公众对谣言消息的立场是识别流行的谣言的关键信号,这也能表明它们的真实性.因此,对谣言的立场分类被 ...
- Note -「狄利克雷前缀和」
学到一个诡异东西,当个 Trick 处理用吧. 现在有一个形如 \(\sum \limits _{i = 1} ^{n} \sum \limits _{d | i} f(d)\) 的柿子,不难发现可以 ...
- 多人共用一个Linux用户, 实现Bash配置文件独立
本文中提到的 账户, 用户 均表示同一概念. 例如 ssh wbourne@192.168.xxx.101, 账户, 用户 指的均是 wbourne. 背景 在工作中, 我们经常会连接Linux服务器 ...