Skip to content

第 19 题:React setState 笔试题,下面的代码输出什么? #18

@mengsixing

Description

@mengsixing

1、第一次和第二次都是在 react 自身生命周期内,触发时 isBatchingUpdates 为 true,所以并不会直接执行更新 state,而是加入了 dirtyComponents,所以打印时获取的都是更新前的状态 0。

2、两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。

3、setTimeout 中的代码,触发时 isBatchingUpdates 为 false,所以能够直接进行更新,所以连着输出 2,3。

输出: 0 0 2 3

Activity

zhanglin-doudou

zhanglin-doudou commented on Feb 22, 2019

@zhanglin-doudou

1、第一次和第二次都是在 react 自身生命周期内,触发时 isBatchingUpdates 为 true,所以并不会直接执行更新 state,而是加入了 dirtyComponents,所以打印时获取的都是更新前的状态 0。

2、两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。

3、setTimeout 中的代码,触发时 isBatchingUpdates 为 false,所以能够直接进行更新,所以连着输出 2,3。

输出: 0 0 2 3

请问一下大佬,isBatchingUpdates的判断条件是什么呀?

mengsixing

mengsixing commented on Feb 22, 2019

@mengsixing
Author

我理解的是:isBatchingUpdates 默认值为 false,当 react 自身的事件处理函数或 react 生命周期触发时,isBatchingUpdates 会被赋值为 true,当更新完成时又会被复原为 false。 @code-coder

azl397985856

azl397985856 commented on Feb 22, 2019

@azl397985856

1、第一次和第二次都是在 react 自身生命周期内,触发时 isBatchingUpdates 为 true,所以并不会直接执行更新 state,而是加入了 dirtyComponents,所以打印时获取的都是更新前的状态 0。
2、两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。
3、setTimeout 中的代码,触发时 isBatchingUpdates 为 false,所以能够直接进行更新,所以连着输出 2,3。
输出: 0 0 2 3

请问一下大佬,isBatchingUpdates的判断条件是什么呀?

#17

xueqingxiao

xueqingxiao commented on Feb 22, 2019

@xueqingxiao

具体可以见 ReactFiberScheduler 中的 performWork 和 performSyncWork。 楼主说的基本是对的,如果有这种 async 的 work 就不执行 batch update 如果没有 async 的就执行 batch update,setTimeout 和 promise 这些要进入 EventLoop 队列的都会被认为是 async work。

etsvain

etsvain commented on Feb 27, 2019

@etsvain

哦也我做对了

mochen666

mochen666 commented on Mar 5, 2019

@mochen666

@azl397985856 在React的setState函数实现中,会根据一个变量 isBatchingUpdate 来判断是直接同步更新this.state还是放到队列中异步更新 。React使用了事务的机制,React的每个生命周期和合成事件都处在一个大的事务当中。在事务的前置钩子中调用batchedUpdates方法修改isBatchingUpdates变量为true,在后置钩子中将变量置为false。原生绑定事件和setTimeout异步的函数没有进入到React的事务当中,或者当他们执行时,刚刚的事务已近结束了,后置钩子触发了,所以此时的setState会直接进入非批量更新模式,表现在我们看来成为了同步SetState。

changed the title [-]关于第19题的见解[/-] [+]第 19 题:React setState 笔试题,下面的代码输出什么?[/+] on Apr 26, 2019
AlertTed

AlertTed commented on May 13, 2019

@AlertTed

很好理解的问题 正常情况下 react是会同步更新数据的 也就是说isBatchingUpdate触发变成true 但是 如果你将state的状态值加入到setTimeout的延迟处理队列中 打印出来的值就是setState之后的值,或者你同时调用setState的第二个参数 也会做到异步操作 获取设置之后的state value

leonwens

leonwens commented on Jun 22, 2019

@leonwens

题目呢???

ggzcg

ggzcg commented on Jul 15, 2019

@ggzcg

做成了 0022 哎。竟然有isBatchingUpdates这种东西 学习了 @yhlben 。

allen3xiaokai

allen3xiaokai commented on Jul 24, 2019

@allen3xiaokai

我打印的 0 0 1 1

LastStranger

LastStranger commented on Jul 27, 2019

@LastStranger

react-hooks时代貌似改写了这种方式,我用react-hooks写法写出来的结果都是0

Bjkb

Bjkb commented on Aug 23, 2019

@Bjkb

@LastStranger

react-hooks时代貌似改写了这种方式,我用react-hooks写法写出来的结果都是0

更新的方式没有更改,首先是因为useEffect函数只运行了一次,其次setTimeout是个闭包,访问到的值一直是0(按照正常的写法setVal(val+1))。以例子来看的话,并没有执行更新的操作。

具体可以参考 issue讨论: facebook/react#14010

27 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @xueqingxiao@flftfqwxf@leonwens@Yolo-0317@soneway

        Issue actions

          第 19 题:React setState 笔试题,下面的代码输出什么? · Issue #18 · Advanced-Frontend/Daily-Interview-Question