跳到主要内容

认识

2023年02月22日
柏拉文
越努力,越幸运

一、认识


useEffect 可以让你在函数中使用副作用,执行时机在浏览器绘制之后。对于 useEffect 执行, React 处理逻辑是采用异步调用 ,对于每一个 effectcallbackReact 会向 setTimeout 回调函数一样,放入任务队列,等到主线程任务完成,DOM 更新,js 执行完成,视图绘制完毕,才执行。所以 effect 回调函数不会阻塞浏览器绘制视图

对于不同的 effect 钩子, 父子组件的执行顺序是: 先子后父

二、语法


useEffect(() => { doSomething },[a,b]);
  • 第一个参数: 初始渲染后触发 doSomething: 组件重新渲染后根据 [a,b] 决定是否触发 doSomething 副作用。(注意副作用是在渲染完成之后执行)

    • doSomething 返回函数:组件销毁时触发 doSomething 返回函数; 组件重新渲染后根据 [a,b] 决定是否触发 doSomething 返回函数,这时候先执行 doSomething 返回函数,后执行 doSomething 副作用。
  • [a,b]:

    • 如果为 [a,b] ,只有 a,b 更新引起的组件重新渲染后才会重新调用 doSomething ,以及 doSomething 返回函数

    • 如果为 [] , 无论组件是否重新渲染,都不会重新调用 doSomething , 以及 doSomething 返回函数

    • 如果没有[a,b] 或者 [] 时,组件每次重新渲染都会调用 doSomething 包括 doSomething 的返回函数

三、用法


3.1 useEffect 无限循环

细节
  1. 如果在useEffect中修改状态,且不加任何条件,那么循环调用useEffect,进入死循环
import React, { useState, useEffect } from "react";

function App() {
const [number, setNumber] = useState(0);
useEffect(() => {
setNumber((state) => {
return state + 1;
});
});
return <div>{number}</div>;
}
export default App;

3.2 useEffect 条件执行

细节
  1. useEffect 如果要限定只是初始渲染执行一次或者根据某个状态变化来执行,需要限制条件

[]空数组: 控制 useEffect 只在初始化时执行

import React, { useState, useEffect } from "react";

function App() {
const [number, setNumber] = useState(0);
useEffect(() => {
setNumber((state) => {
return state + 1;
});
},[]);
return <div>{number}</div>;
}
export default App;

[x状态,y状态,……]: 控制 useEffect 只在初始化、x状态、y状态等发生变化时执行

import React, { useState, useEffect } from "react";

function App() {
const [number, setNumber] = useState(0);
useEffect(()=>{
console.log('哈哈');
},[number]);
return <div>{number}</div>;
}
export default App;

3.3 useEffect 销毁副作用

通过return ()=>{}来销毁副作用

import React, { useState, useEffect } from "react";

function App() {
const [number, setNumber] = useState(0);
useEffect(() => {
const timer = setTimeout(() => {
setNumber((state) => {
return state + 1;
});
});
return ()=>{
clearTimeout(timer);
}
}, []);
return <div>{number}</div>;
}
export default App;

四、问题


4.1 useLayoutEffect 与 useEffect 的区别? 什么时候用 useLayoutEffect,什么时候用 useEffect

  • useLayoutEffect: 初始渲染或者状态更新之后, 在 commit 阶段中同步执行, 所以 useLayoutEffect callback 中代码执行会阻塞浏览器绘制。 useLayoutEffect 是在 DOM 更新之后,浏览器绘制之前,这样可以方便修改 DOM,获取 DOM 信息,这样浏览器只会绘制一次。修改 DOM ,改变布局就用 useLayoutEffect

  • useEffect: 初始渲染或者状态更新之后, 在 commit 阶段完成以后异步执行,所以 effect 回调函数不会阻塞浏览器绘制视图。useEffect 执行是在浏览器绘制视图之后,如果修改 DOM 布局放在 useEffect ,那 useEffect 执行是在浏览器绘制视图之后,接下来又改 DOM ,就可能会导致浏览器再次回流和重绘。而且由于两次绘制,视图上可能会造成闪现突兀的效果。除修改 DOM ,改变布局的场景外,其他情况都用 useEffect