Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
背景
在 ant-design/ant-design#45653 的 PR 中,为组件添加
autoFocus
事件导致在 React 16 的 test case 中不会触发onFocus
事件。问题由来
为错误打 console 可以发现,React 内部已经触发了
react-focus
事件。问题是 React 16 没有把这个事件正确触发。错误信息来自于
rc-trigger
调用了flushSync
导致生命周期报错。相关部分
rc-slider
autoFocus
属性会通过useEffect
触发handleRef.current.focus
方法触发聚焦。rc-trigger
rc-trigger
对action
标记为focus
的事件添加监听事件,并且触发对应的triggerOpen
逻辑。在 #415 中,
rc-trigger
为支持disabled
元素也能触发open
而同时兼容旧版不支持pointerEvent
浏览器所以同时保留了mouseEvent
监听。所以当元素被悬浮时,会触发onPointerEnter
和onMouseEnter
事件。而在 React 18 中,这两个事件会被 batch update。导致通过
open
是否变化来判断要触发onOpenChange
的事件因为闭包问题导致会触发两次。所以在 #415 中,使用了flushSync
确保两个事件之间不被 batch update 掉。报错原因
useEffect
中触发的focus
事件调用focus
并触发rc-trigger
的triggerOpen
方法后调用flushSync
事件。在 React 16 中,useEffect
被视为生命周期进行中,导致在此不允许调用flushSync
。而在 React 18,useEffect
中不再视为上一个 render 的生命周期,因而focus
事件触发的flushSync
不会出现flushSync was called from inside a lifecycle method
错误。解决方案
使用
useRef
记录最后触发的open
状态,如果相同就不再触发。该ref
每次 render 都会被重置。