We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
参考文章: 深入理解 React useLayoutEffect 和 useEffect 的执行时机
useEffect useEffect 的执行时机:赋值给 useEffect 的函数会在组件渲染到屏幕之后执行。
useLayoutEffect useLayoutEffect 的执行时机:赋值给 useLayoutEffect 的函数会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。
render {创建React Element; diffing算法} -> pre-commit {getSnapshotBeforeUpdate; 注册 useEffect/useLayout 的回调函数} -> commit {Virtual DOM To DOM} {由于JS线程与浏览器渲染线程互斥,此处继续执行同步代码: 生命周期方法/useLayoutEffect此前注册的回调函数 } -> 渲染到浏览器视口 -> 渲染线程结束后,空闲阶段通知JS线程执行队列中的 useEffect 回调函数。
注意是此处是调度 useEffect 内注册的方法,不是执行。在这个阶段,会把使用了 useEffect 组件产生的生命周期函数入列到 React 自己维护的调度队列中,给予一个普通的优先级,让这些生命周期函数异步执行。 这里也可以看出 useEffect 和 useLayoutEffect 的一点区别:useEffect 是异步执行的。
commit 阶段操作参考React-Fiber
commitWork 如果遇到了类组件的 fiber 节点,不会做任何操作,会直接 return,进行收尾工作,然后去处理下一个节点,这点很容易理解,类组件的 fiber 节点没有对应的真实 DOM 结构,所以就没有相关操作
useEffect 产生函数的真正调用时机是在 requestIdleCallback 处。见React-Fiber
注意:useEffect 的异步执行主要是从人机交互方面体现的,假设 useEffect 是同步执行的,useEffect 中有一个数据请求的操作,那么就表明,在数据请求时,用户的一系列交互行为是无法被反馈的,这样会很给人不好的应用体验,你说对不对呢?
The text was updated successfully, but these errors were encountered:
useEffect 在渲染时是异步执行,并且要等到浏览器将所有变化渲染到屏幕后才会被执行。 useLayoutEffect 在渲染时是同步执行,其执行时机与 componentDidMount,componentDidUpdate 一致
useLayoutEffect,因为从源码中调用的位置来看,useLayoutEffect的 create 函数的调用位置、时机都和 componentDidMount,componentDidUpdate 一致,且都是被 React 同步调用,都会阻塞浏览器渲染。
同上,useLayoutEffect 的 detroy 函数的调用位置、时机与 componentWillUnmount 一致,且都是同步调用。useEffect 的 detroy 函数从调用时机上来看,更像是 componentDidUnmount (注意React 中并没有这个生命周期函数)。
可以看到在流程9/10期间,DOM 已经被修改,但但浏览器渲染线程依旧处于被阻塞阶段,所以还没有发生回流、重绘过程。由于内存中的 DOM 已经被修改,通过 useLayoutEffect 可以拿到最新的 DOM 节点,并且在此时对 DOM 进行样式上的修改,假设修改了元素的 height,这些修改会在步骤 11 和 react 做出的更改一起被一次性渲染到屏幕上,依旧只有一次回流、重绘的代价。 如果放在 useEffect 里,useEffect 的函数会在组件渲染到屏幕之后执行,此时对 DOM 进行修改,会触发浏览器再次进行回流、重绘,增加了性能上的损耗。
Sorry, something went wrong.
No branches or pull requests
React - useLayoutEffect 和 useEffect 的执行时机
参考文章: 深入理解 React useLayoutEffect 和 useEffect 的执行时机
React 官方解释
useEffect
useEffect 的执行时机:赋值给 useEffect 的函数会在组件渲染到屏幕之后执行。
useLayoutEffect
useLayoutEffect 的执行时机:赋值给 useLayoutEffect 的函数会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。
从 React 执行流程解释
(重点来了!) 但由于 JS 线程和浏览器渲染线程是互斥的,因为 JS 虚拟机还在运行,即使内存中的真实 DOM 已经变化,浏览器也没有立刻渲染到屏幕上。此时会进行收尾工作,同步执行对应的生命周期方法,我们说的componentDidMount,componentDidUpdate 以及 useLayoutEffect(create, deps) 的 create 函数都是在这个阶段被同步执行。
The text was updated successfully, but these errors were encountered: