react 【useEffect 和 useLayoutEffect 的区别】
前言
useEffect和useLayout,都是react为函数组件提供的取代class组件周期,componentDidMount,componentDidUpdate的hook。它们的作用完全一致,只是调用的时机不同
调用时机
useEffect:
与componentDidMount、componentDidUpdate不同的是,在浏览器完成布局与绘制之后,传给useEffect的函数会延迟调用
useLayoutEffect
它相当于class组件的componentDidMount和componentDid,它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect
内部的更新计划将被同步刷新,
适用场景
1.组件的入场动画
(1)假定现在有一个弹框,假定需要在弹框出现的时候,加入一个缩放效果,那么使用useEffect和useLayoutEffect会有两种不同的结果
useEffect:
代码:
const [ani, setAni] = useState(false); //是否展示弹框动画,默认为false useEffect(() => { setAni(true); //mount之后,显示动画 }, []); return ( <div className={s.msk}> <div className={s.wrap + ` ${ani ? s.animation : ""}`}> <span>弹框</span> </div> </div>
样式:
.msk { ...//其他样式 .wrap { transition: all 0.3s; transform: scale(0.7); .flex-center-w; } .animation { transform: scale(1); } }
效果: 可以看到弹框出现了由小变大动画
现在将useEffect 改成useLayoutEffect,可以看到,弹框一如既往,并没有出先由小变大的动画,为什么呢?
更新流程
在使用useEffect时,浏览器第一次渲染时,并没有将.animation样式赋给弹框,而是在第二次渲染时赋予,弹框的样式发生了改变,所以会出现动画效果,而使用useLayoutEffect时,useLayouEffect内部的更新被同步更新至渲染输出上,在浏览器第一次渲染时.animation样式就已经赋给弹框,所以就不存在样式的改变,自然就没有动效