拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 了解useEffect()行为和额外的重新渲染

了解useEffect()行为和额外的重新渲染

白鹭 - 2022-02-12 2095 0 0

我正在使用以下虚拟组件进行一些测验,在执行时(在控制台中)我得到以下结果:

Rendering:  0
Triggered:  0
Rendering:  4
Triggered:  4
Rendering:  4

我很难理解为什么。

第一次渲染:

  • 设定index0
  • 运行 useEffectundefined不是0
  • useEffect 请求设定index4

第二次渲染:

  • index4
  • 为什么useEffect body又被执行了?

第三次渲染:

  • 为什么会有重新渲染?

我期望的是:

Rendering:  0
Triggered:  0
Rendering:  4

我是否跳过了一些非常明显的东西?你能帮我理解它是如何在幕后作业的吗?

const Example = React.memo(() => {
    const [index, setIndex] = React.useState(0)
    console.log('Rendering: ', index)

    React.useEffect(() => {
        console.log('Triggered: ', index)
        setIndex(4)
    }, [index])

    return <h1>{index}</h1>
})

ReactDOM.render(<Example />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

uj5u.com热心网友回复:

重新渲染的数量实际上是正确的。让我们分析一下会发生什么:


  1. 渲染 0 - 这是在安装第一次渲染时(在这种状态下,每个useEffect都自动运行)

  1. 触发 0 - 这是初始触发useEffect

  1. 渲染 4 - 此重新渲染是因为您将新状态设定index4

  1. 触发 4 - 这是因为您index从 0 更改为 4而触发

  1. 渲染 4 - 这是因为状态从4to更改为运行4(即使值相同,它也会触发组件重新渲染,因为 React 不知道您是否设定了相同的状态,它需要再次运行)。在此重新渲染中, useEffect未运行,因为index再次为 4。

基本原理

如果组件在任何时候发生任何变化,例如useState useContext, customHook,则该组件将需要重新渲染。如果父组件重新渲染也会发生这种情况,即使您的组件没有任何更改,子组件也会重新渲染。

其他重新渲染提示和信息

为了防止父组件发生不必要的子组件重新渲染,您可以使用React.memo,如果 props 更改,这将重新渲染您的组件,但不会阻止您的组件在 state 或上述任何钩子发生更改时重新渲染。

如果这看起来是多余的,听起来很像,但有必要让 react 确保它具有最新状态。像这样运行 JS 比拥有一些检查更改的状态存储器要快,而且它对开发人员更透明(以及VDOM的创建方式)

uj5u.com热心网友回复:

无法达到预期的输出。

useEffect 在组件挂载时渲染,并且在状态更改(索引)时每次重新渲染时渲染。

const Example = () => {
    const [index, setIndex] = React.useState(0)
    console.log('Rendering: ', index)
    React.useEffect(() => {
        console.log('Triggered: ', index)
        setIndex(4)
    }, [index])

    return <h1>{index}</h1>
}

输出:

  • 渲染:0 => 组件第一次挂载时,该时间索引为 0
  • 触发:0 => 挂载 useEffect 触发,状态更新(0 到 4)
  • 渲染:4 => 组件重新渲染,因为状态已从(0 变为 4)
  • 已触发:4 => useEffect 重新触发,因为状态已更改(0 到 4)
  • 渲染:4 => Componet 重新渲染,因为要检查状态是否已更改(4 到 4,确认没有任何变化

uj5u.com热心网友回复:

useEffect 的作业方式是它只在页面组件渲染后运行。

希望这能帮助你理解。

第一个渲染索引为 0。

Rendering:  0

它触发了useEffect。

Triggered:  0

索引在 useEffect 中更新,但不在组件中。然后 render 将索引更新为 4。

Rendering:  4

useEffect 运行,因为索引已更改。

Triggered:  4

组件再次渲染,但索引仍为 4,因此 useEffect 不会再次运行。

Rendering:  4
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *