React报错之Rendered more hooks than during the previous render
2023-02-18 16:40:33 时间
正文从这开始~
总览
当我们有条件地调用一个钩子或在所有钩子运行之前提前返回时,会产生"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
调用之间保留钩子的状态。
相关文章
- Unable to start the daemon process
- docker高级篇第二章-分布式存储之实战案例:3主3从redis集群扩容配置
- 解决net不是此命令的问题
- 在多分类任务实验中用torch.nn实现dropout
- 在多分类任务实验中手动实现实现dropout
- Ubuntu 20.04 使用参考博客
- 多分类任务中不同隐藏单元个数对实验结果的影响
- 多分类任务中不同隐藏层层数对实验结果的影响
- 利用torch.nn实现前馈神经网络解决 多分类 任务使用至少三种不同的激活函数
- 利用torch.nn实现前馈神经网络解决 二分类 任务
- torch.nn.BCELoss用法
- 利用torch.nn实现前馈神经网络解决 多分类 任务
- R7000P Ubuntu20.04 安装 Realtek 8852 无线网卡驱动
- 邻接矩阵的相乘的意义
- 分类问题中评价指标
- 矩阵求导
- Jupyter Notebook设置主题
- 逻辑回归从零开始实现
- Pytorch 实现多层感知机
- 逻辑回归torch.nn实现