即使状态没有改变,为啥 setState 会导致太多的重新渲染错误
Posted
技术标签:
【中文标题】即使状态没有改变,为啥 setState 会导致太多的重新渲染错误【英文标题】:Why setState causes too many rerender Error even though the state hasn't changed即使状态没有改变,为什么 setState 会导致太多的重新渲染错误 【发布时间】:2021-10-21 21:52:52 【问题描述】:您好,我现在正在学习 React,但遇到了状态问题..
我知道当状态改变时,组件会重新渲染,UseEffect 中的代码只运行一次。 但是我无法准确解释为什么我在 JSX 或渲染语法中编写 setState 时会发生无限渲染。
以下代码导致无限重新渲染
import React, useState, useEffect from 'react'
const index = () =>
const [active, setActive] = useState(false);
console.log("render", active);
setActive(false);
return (
<div>
</div>
)
export default index
但是下面的代码即使一直调用setState也没问题。
import React, useState, useEffect from 'react'
const index = () =>
const [active, setActive] = useState(false);
console.log("render", active);
useEffect(() =>
setInterval(()=>
console.log("run")
setActive(true)
,0);
, [])
return (
<div>
</div>
)
无论状态值如何,setState 都会触发重新渲染吗? 我想知道在 useEffect 之外使用 setState 会导致错误的确切原因。
【问题讨论】:
这个好像和组件生命周期有关;第一个示例在渲染之前运行setActive
,此时循环可以被 React 中止或重新启动,而第二个示例在渲染完成后调用它,此时 React 能够更好地避免不必要的重新渲染
这能回答你的问题吗? Difference between with and without useEffect in react functional component
【参考方案1】:
发生这种情况是因为,在第一种情况下,当未使用 useEffect 时, 您在声明后立即更新您的状态。 即使您再次将状态设置为 false,但对于响应,状态已更新。 React 的第一条经验法则是,如果发生状态更新,组件将重新渲染。
这就是您获得无限重新渲染的原因。
您的代码遵循以下流程:
-
声明状态变量并将值传递为 false
将状态更新为 false
状态已更新,因此组件重新呈现。
再次执行第 1 步。
在第二种情况下,使用了useEffect,你的状态只有在组件被挂载时才会更新,这意味着之后任何状态更新都不会触发你的useEffect。
【讨论】:
“只有当组件被挂载时,你的状态才会更新” - 在useEffect
内部,有setInterval
调用,它会定期调用setActive(true)
。为什么每次调用 setActive(true)
时组件不重新渲染?原因是,如果旧状态和以前的状态相同,react 将退出状态更新并且不会重新渲染组件但是,如下面的答案中所述,React 可能需要在退出之前再次渲染组件状态更新。【参考方案2】:
基于 React 文档:https://reactjs.org/docs/hooks-reference.html#usestate
setState 函数用于更新状态。它接受一个新的状态值并将组件的重新渲染排入队列。
还有一个补充:https://reactjs.org/docs/hooks-reference.html#bailing-out-of-a-state-update
如果您将 State Hook 更新为与当前状态相同的值,React 将退出而不渲染子级或触发效果。 (React 使用 Object.is 比较算法。)请注意,React 可能仍需要在退出之前再次渲染该特定组件。
这是重要的部分:React 可能仍需要在退出之前再次渲染该特定组件。
所以是的,即使值相同,组件仍可能重新渲染。
【讨论】:
如果你在setTimeout(...)
:setTimeout(() => setActive(false), 0)
中封装setActive
调用,那么React 会按预期退出状态更新;仍然不确定为什么 React 没有在函数组件的顶层调用 setActive
退出以上是关于即使状态没有改变,为啥 setState 会导致太多的重新渲染错误的主要内容,如果未能解决你的问题,请参考以下文章
更新状态 - 为啥在调用 setState 时创建新的状态副本?
为啥即使在有状态小部件中使用 setstate 也无法获取更新的变量。因为我想在新的 TabBar 选项上更新我的 Container