useEffect
是 React 提供的一个 Hook,Hook 是 React 16.8 的新增特性,是一种复用 state
逻辑的方式,它让在函数组件使用 state
成为可能。useEffect
是一个常用的 Hook,用于在 React 更新 DOM 之后执行副作用,依赖的变化、生命周期的变化都会影响它的执行,本文通过实验验证它的具体行为。
useEffect
是啥
useEffect
是用来处理副作用的,那啥是副作用?发送网络请求、手动变更 DOM
、记录日志这些与 React 更新 DOM
无关的操作都可算是副作用。useEffect
可以看做是 componentDidMount
、componentDidUpdate
和 componentWillUnmount
三个生命周期函数的组合。它接收的第一个参数是一个函数,这个函数用来执行副作用,下文称为函数体,函数体可以有一个函数作为其返回值,下文称为返回体,用来清除副作用。第二个可选参数接收一个数组,用来指定关注的依赖。
实验记录
我写了一个 demo 用来实验 useEffect
在依赖、生命周期发生变化时的执行情况。无依赖的情况是指不传入第二个参数,而空依赖是指传入一个空数组。
函数体
无依赖 | 空依赖 | 一个依赖 | 两个依赖 | |
---|---|---|---|---|
进入页面 | 执行一次 | 执行一次 | 执行一次 | 执行一次 |
依赖发生变化 | 组件状态发生变化就执行 | 不执行 | 对应依赖发生变化时执行一次 | 至少一个依赖发生变化时执行一次 |
页面销毁 | 不执行 | 不执行 | 不执行 | 不执行 |
返回体
无依赖 | 空依赖 | 一个依赖 | 两个依赖 | |
---|---|---|---|---|
进入页面 | 不执行 | 不执行 | 不执行 | 不执行 |
依赖发生变化 | 组件状态发生变化就执行 | 不执行 | 对应依赖发生变化时执行一次 | 至少一个依赖发生变化时执行一次 |
页面销毁 | 执行一次 | 执行一次 | 执行一次 | 执行一次 |
通过实验,可以知道几点结论:
- 默认情况下(无依赖)
useEffect
会在每次渲染后都执行,不管渲染是因为“挂载”还是“更新”导致的。 - 空依赖下的
useEffect
是componentDidMount
和componentWillUnmount
的组合体,组件状态发生变化时,它并不执行。 - 可以指定依赖来优化
useEffect
的执行次数,避免性能问题。 - 多个依赖同时发生变化时,只会触发一次渲染,
useEffect
也只会执行一次。 useEffect
会在调用一个新的 effect 之前对前一个 effect 进行清理,因此返回体只能拿到前一次的state
(需要拿最新的话可以考虑使用useRef
)。