useEffect和useLayoutEffect区别
useEffect和useLayoutEffect作为组件的副作用,本质上是一样的。共用一套结构来存储effect链表。整体流程上都是先在render阶段,生成effect,并将它们拼接成链表,存到fiber.updateQueue上,最终带到commit阶段被处理。他们彼此的区别只是最终的执行时机不同,一个异步一个同步,这使得useEffect不会阻塞渲染,而useLayoutEffect会阻塞渲染。
useLayoutEffect可以解决更新dom时候屏幕闪烁的问题
useEffect在浏览器渲染完成后执行
useLayoutEffect在浏览器渲染前执行
useLayoutEffect总是比useEffect先执行
useLayoutEffect里面的任务最好影响了Layout(布局)
import React, {useState, useLayoutEffect, useEffect} from "react";
import ReactDOM from "react-dom";
function App() {
const [n, setN] = useState(0)
const onClick = ()=>{
setN(i=>i+1)
}
useEffect(()=>{
console.log("useEffect")
})
useLayoutEffect(()=>{ // 改成 useEffect 试试
console.log("useLayoutEffect")
})
return (
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>Click</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
注意:为了用户体验最好优先使用useEffect
import React, {useState, useRef, useLayoutEffect, useEffect} from "react";
import ReactDOM from "react-dom";
function App() {
const [n, setN] = useState(0)
const time = useRef(null)
const onClick = ()=>{
setN(i=>i+1)
time.current = performance.now()
}
useLayoutEffect(()=>{ // 改成 useEffect 试试
if(time.current){
console.log(performance.now() - time.current)
}
})
return (
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>Click</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);