目录
useEffect
基本上绝大多数的情况下使用useEffect就够了。需要注意的是useEffect的副作用调用不会阻塞dom元素的渲染,这和class组件componentDidMount或componentDidUpdate不同,componentDidMount或componentDidUpdate是dom更新后同步运行的,通常来说,如果不影响你的使用,useEffect这种运行方式有助于提高性能。
但是,如果你的副作用会导致dom元素的显示修改,这样会有两次dom修改,这时不应该使用useEffect,而应该使用useLayoutEffect。否则你会看到界面的修改产生闪动,通常会使用useLayoutEffect取代useEffect就是出于这种情况。
useLayoutEffect
useLayoutEffect和useEffect的使用方式完全一样。
useLayoutEffect的副作用调用在dom变更后马上发生,一般来说,如果你想在dom变更后测量一些dom元素的位置或者滚动条位置或者dom元素的样式后再设置新的dom显示,会使用useLayoutEffect。
这个运行的过程和componentDidMount或componentDidUpdate完全一样,代码会在dom更新后马上运行,这样允许你重新渲染一次dom。
总结
- 如果dom更新后想通过更新后的dom属性再次渲染,使用useLayoutEffect。
- 如果不需要dom更新或者dom更新无需被观测,则使用useEffect。
例子
useEffect的效果会产生一次闪烁,useLayoutEffect则没有刷新闪烁。
import React, { useState, useEffect, useLayoutEffect } from 'react';
import './index.less'
const random = () => {
return 10 + Math.random() * 200
}
const App = () => {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
useEffect(() => {
if (count1 === 0) {
setCount1(random());
}
}, [count1]);
useLayoutEffect(() => {
if (count2 === 0) {
setCount2(random());
}
}, [count2]);
return (
<div className="useLayoutEffect">
<div onClick={() => setCount1(0)}>useEffect:{count1}</div>
<div onClick={() => setCount2(0)}>useLayoutEffect:{count2}</div>
</div>
);
};
export default () => <App />;