有人可以从事件循环的角度向我解释一下吗?

Fre*_*d A 5 javascript reactjs

我这里有以下 React 片段

****** Example.js *******

    import React from 'react';

    export default const SampleApp =  props => {
        const [text, setText] = React.useState('Some name in here');

        console.log(`[1] The value of the text is - ${text}`); // ---(1)

        React.useEffect(() => {
            setText('Ohhh yeah ma boy');
            console.log(`[2] The value of the text is - ${text}`); // --- (2)
        }, []);

        React.useEffect(() => {
            console.log(`[3] The value of the text is - ${text}`); // --- (3)
            setText('Yare yare daze');
        }, [text]);

        console.log(`[4] The value of the text is - ${text}`); // --- (4)

        return (
            <div>{text}</div>
        )
    }
Run Code Online (Sandbox Code Playgroud)

当我运行它时,它会给我以下控制台消息

    [1] The value of the text is - Some name in here
    [4] The value of the text is - Some name in here
    [2] The value of the text is - Some name in here
    [3] The value of the text is - Some name in here
    [1] The value of the text is - Yare yare daze
    [4] The value of the text is - Yare yare daze
    [3] The value of the text is - Yare yare daze
    [1] The value of the text is - Yare yare daze
    [4] The value of the text is - Yare yare daze
Run Code Online (Sandbox Code Playgroud)

我不明白为什么“Ohhh Yeah ma boy”值没有出现在控制台消息中?

5 5 5 5 5是否与以下代码在运行时在控制台消息上生成值(尽管我希望它显示)的原因相同0 1 2 3 4

for (var i = 0; i < 5; i++) {
    setTimeout(function() { console.log(i); }, i * 1000 );
}
Run Code Online (Sandbox Code Playgroud)

这意味着在事件循环中,useState 在第二次重新渲染时已经更新了 2 次,而第二个 useEffect 仍在队列中?

Dre*_*ese 4

在 React 中,渲染周期中排队的所有状态更新都按照它们排队的顺序异步处理,并进行批处理。

鉴于提供的代码:

const SampleApp =  props => {
    const [text, setText] = React.useState('Some name in here');

    console.log(`[1] The value of the text is - ${text}`); // ---(1)

    React.useEffect(() => {
        setText('Ohhh yeah ma boy');
        console.log(`[2] The value of the text is - ${text}`); // --- (2)
    }, []);

    React.useEffect(() => {
        console.log(`[3] The value of the text is - ${text}`); // --- (3)
        setText('Yare yare daze');
    }, [text]);

    console.log(`[4] The value of the text is - ${text}`); // --- (4)

    return (
        <div>{text}</div>
    )
}
Run Code Online (Sandbox Code Playgroud)

在初始渲染周期,输出将为

[1] The value of the text is - Some name in here
[4] The value of the text is - Some name in here
[2] The value of the text is - Some name in here
[3] The value of the text is - Some name in here
Run Code Online (Sandbox Code Playgroud)
  1. 控制台作为state 的无意副作用[1]运行,然后控制台运行也作为state的无意副作用运行。一旦渲染完成,钩子就会运行,首先是“onMount”效果日志记录,然后是第二个日志记录,两者都带有状态。'Some name in here'[4]'Some name in here'useEffect[2][3]'Some name in here'
  2. 安装效果钩子将状态更新排入队列'Ohhh yeah ma boy'
  3. 第二个效果将状态更新放入队列'Yare yare daze'
  4. 两个排队的更新都会触发重新渲染,并在下一个渲染周期之前进行处理。状态用 更新'Ohhh yeah ma boy',然后用 更新'Yare yare daze'

下一个渲染周期的输出将是

[1] The value of the text is - Yare yare daze
[4] The value of the text is - Yare yare daze
[3] The value of the text is - Yare yare daze
Run Code Online (Sandbox Code Playgroud)
  1. 控制台作为state 的无意副作用[1]运行,然后控制台运行也作为state的无意副作用运行。渲染完成后,第二个钩子就会运行,并使用 state进行记录。'Yare yare daze'[4]'Yare yare daze'useEffect[3]'Yare yare daze'
  2. 第二个效果钩子将状态更新排入队列'Yare yare daze'
  3. 排队的更新会触发重新渲染,并在下一个渲染周期之前进行处理。状态更新为'Yare yare daze'.

下一个“渲染周期”的输出将是

[1] The value of the text is - Yare yare daze
[4] The value of the text is - Yare yare daze
Run Code Online (Sandbox Code Playgroud)

请注意,我在渲染周期周围添加了引号。

  1. 作为 React 协调过程的一部分,组件在“渲染阶段”进行渲染,以计算 ReactTree diff。由于状态与之前的渲染结果的值相同,因此react是Bailing out of a state update
  2. 控制台作为state 的无意副作用[1]运行,然后控制台运行也作为state的无意副作用运行。'Yare yare daze'[4]'Yare yare daze'

下面的 React 生命周期图应该有助于区分渲染组件以计算 ReactTree 时的“渲染阶段”和组件渲染到 DOM 时的“提交阶段”。请注意,效果在“提交阶段”运行

在此输入图像描述

问题

我不明白为什么“Ohhh Yeah ma boy”值没有出现在控制台消息中?

如上所述,第一个排队状态更新被第二个排队状态更新覆盖,因此您根本看不到它。

是否与以下代码在运行时在控制台消息上生成值 5 5 5 5 5 尽管我希望它显示 0 1 2 3 4 的原因相同?

for (var i = 0; i < 5; i++) {
    setTimeout(function() { console.log(i); }, i * 1000 );
}
Run Code Online (Sandbox Code Playgroud)

不,不是真的。在此示例中,您实例化 5 个超时,然后更改正在记录的变量i。换句话说,每个超时回调引用相同的变量(和内存中的值),并且 for 循环会改变该值,因此当超时到期时,它们都会记录 的当前值i,即5