react useEffect 是hooks 中最难以理解的一个hooks, 在使用的时候时候需要理解他的执行, 更新到底发生了什么, 已经后续ui更新问题
先了解一下useEffect 函数的各个参数分别是什么, 为什么要写这个参数, 不写有什么问题?
useEffect(() => {
return () => {};
}, []);
- 上面是一个
useEffect
函数完整的写法, 来分析一下useEffect
, 其中useEffect(() => {})
中的箭头函数
我个人理解为是useEffect
的effect
函数, 也就是副作用函数,effect
函数中的 return 后面的箭头函数
个人理解为useEffect
函数的返还函数, 这个函数在 当前组件卸载的时候会执行, 最后useEffect(() => { return () => {}; }, []);
中的最后一个参数[]
, 是useEffect
函数的依赖项, 表示当前useEffect
依赖的数据发生改变后执行, 下面上图
function Test() {
useEffect(() => {
console.log('useEffect1')
})
useEffect(() => {
console.log('useEffect2')
return () => {
console.log('useEffect2 卸载了')
}
})
useEffect(() => {
console.log('useEffect3')
return () => {
console.log('useEffect3 卸载了')
}
}, [])
return (
<div>Test</div>
)
}
export default Test;
下面贴出 运行结果
下面增加一点东西, 来证明一下 上面的理解
import {useEffect} from "react";
function Test() {
const [n ,setN] = useState(0);
useEffect(() => {
console.log('useEffect1')
})
useEffect(() => {
console.log('useEffect2 n改变之后执行')
},[n])
useEffect(() => {
console.log('useEffect3')
return () => {
console.log('useEffect3 组件卸载了')
}
}, [])
return (
<div>
<div>n: {n}</div>
<button onClick={() => setN(n+1)}>n+1</button>
</div>
)
}
export default Test;
function App() {
const [isShow, setIsShow] = useState(true);
return (
<div>
{isShow && <Test></Test>}
<button onClick={()=> setIsShow(false)}>隐藏Test</button>
</div>
)
}
ReactDOM.render(<App />, document.getElementById(('root')))
来看看这段代码的执行结果
- 在组件初始化, 三个
effect
函数都会执行, 这个是没问题的, 下面来看看组件中的数据改变了是怎么执行的
如图所示, 我们点击 n+1按钮
后, n
的值发生了改变, useEffect1
和useEffect2
执行了 ,而useEffect3
并没有执行, 这是为什么呢?
通过上面的图片可以看出来, useEffect1
和useEffect2
的区别是, useEffect1
函数中的依赖项 并没有设置, 这个时候, useEffect1
函数在组件的初始化, 更新 都会执行, 而useEffect2
函数设置了依赖项 为 n
, 就是在n 变化和初始化的时候会执行, 在来看看useEffect3
函数为什么在页面初始化之后执行, 并且组件中有其他数据改变并不会执行, 这个我也是看别的博客了解来了的, 是因为useEffect3
函数的依赖项设置的是 []
不依赖任何数据, 也就是页面初始化的时候会执行, 好了到这里我们弄清楚了 useEffect1
和useEffect2
执行了 ,而useEffect3
并没有执行, 下面来看看 点击隐藏test
组件会发生什么
看到 useEffect3
的返还函数被执行了, 这里就可以当成class
组件的卸载阶段
最后贴上我自己总结的useEffect 函数的总结, 如有错误, 感谢指正
useEffect(()=> { return ()=> {}},[])
- 参数 1 effect 函数 => 发送请求 修改数据 ...
- 参数 2 effect 函数依赖参数 决定effect 的更新方式
- return 返还函数 ==> 组件要卸载的时候做一些事情
执行机制
- 挂载阶段 => 1 先执行useEffect 函数 , 并把effect 函数存入队列等待执行
- 挂载完成 => 执行effect 函数队列
更新阶段
- 执行新的的useEffect 函数 , 并肩effect 函数存入队列等待等待执行
- 执行返还函数队列, 并观察返还函数书否有依赖参数, 有依赖参数, 追踪依赖参数是否改变, 改变执行, 没有改变不执行
- 执行effect 函数队列, 观察effect 函数是否有依赖参数,有依赖参数, 追踪依赖参数是否改变, 改变执行, 没有改变不执行
卸载阶段
- 1 执行返还函数队列