About React @ Sun, Feb 12, 2023 6:18 PM
About React @ Sun, Feb 12, 2023 7:33 PM
Expand 11 lines ...
12

12

13
+ [Update to allow components to render undefined](https://github.com/reactwg/react-18/discussions/75)
13
+ [Update to allow components to render undefined](https://github.com/reactwg/react-18/discussions/75)
14
+ [Automatic batching for fewer renders in React 18](https://github.com/reactwg/react-18/discussions/21)
14
+ [Automatic batching for fewer renders in React 18](https://github.com/reactwg/react-18/discussions/21)
15
+
+ 
15

16

17
+

16
## groups multiple state updates into a single re-render
18
## groups multiple state updates into a single re-render
17

19

18
This is because React used to only batch updates *during* a browser event (like click), but here we’re updating the state *after* the event has already been handled.  
20
This is because React used to only batch updates *during* a browser event (like click), but here we’re updating the state *after* the event has already been handled.  
Expand 48 lines ...
67
  });
69
  });
68
};
70
};
69
```
71
```
72
+

73
+

74
+
### [How does this affect the timing of state updates queued in the commit and passive effect phases?](https://github.com/reactwg/react-18/discussions/21#discussioncomment-818291)
75
+

76
+
1. Updates queued in the commit phase (`componentDidMount`/`componentDidUpdate`/`useLayoutEffect`) are executed synchronously
77
+
2. Updates queued in the passive effects phase (`useEffect` callbacks) are deferred to the end of the effects phase  
78
+
    + Effects originating from intentional user-initiated events (like clicks, key presses, etc — we call them discrete, [here's the list](https://github.com/facebook/react/blob/a8a4742f1c54493df00da648a3f9d26e3db9c8b5/packages/react-dom/src/events/ReactDOMEventListener.js#L294-L350)) now **run synchronously at the end of the current task** ([facebook/react#21150](https://github.com/facebook/react/pull/21150)). This gives them consistent timing. In Legacy roots, they are unfortunately inconsistent and we can't fix that ([facebook/react#20074 (comment)](https://github.com/facebook/react/issues/20074#issuecomment-811296789)). So I would expect setting state from such effects to also be synchronous.
79
+
    + Updates queued in passive effects are scheduled to run at different priorities after all passive effects run.
80
+
    + The priority they're scheduled at depends on how the original update(s) were scheduled. Most of the time, updates inside of passive effects are flushed synchronously in a task with normal priority, at the latest. This is true even if the original update was inside a discrete event, flush sync, a timeout, promise tick, or transition.
81
+
    + The only time this is different (currently) is in offscreen trees. Those passive effects are scheduled in a task at Idle priority.
82
+
    + The "passive effect phase" ends when all effects have run. During that phase, updates may be scheduled, but they will run after the passive effect phase ends, according to their priority and how they were scheduled.
83
+

84
+
### 过去存在的误解
85
+

86
+
```js
87
+
setState(1);
88
+

89
+
setTimeout(() => {
90
+
  setState(2)
91
+
}, 0)
92
+
// 过去认为会批量更新
93
+
```
94
+

95
+
The updates outside `setTimeout` will be batched together and updates inside `setTimeout` will be batched together separately so it will be 2 separate renders.
96
+
As far as I understand since the code inside `setTimeout` is asynchronous and will be executed after some delay(until event loop pops from the task queue and pushes to the call stack) hence React will not be batching it.
97
+
> I know I also saw a mention of "5ms" timing somewhere, but I think that was in reference to how long React will work before yielding back to the browser, and I may have misinterpreted that as "React will batch updates across ticks that occur within 5ms of each other".
98
+

99
+
I am not sure about the 5ms timing, but batching isn't related to queuing within 5ms as far as I understand, batching makes sure that app isn't rendered until it executes the whole callback. But If we use the concurrent api `startTransition` instead of `setTimeout` then the `startTransition` will be executed immediately and the updates inside it will be marked as transition which could be interrupted incase of some urgent update (click) kicking in.