一. 作用
useEffect相当于 componentDidMount(组件挂载),componentDidUpdate(组件更新) 和 componentWillUnmount(组件将要销毁) 这三个生命周期函数的组合。
二.用法
useEffect有两个参数,第一个参数是一个回调函数,第二个参数是一个数组,这个数组中的元素都是依赖,每当依赖发生改变,就会触发第一个函数的执行。
三.重要理解
1.第二个参数存放变量,当数组存放变量发生改变时,第一个参数,逻辑处理函数将会被执行
2.第二个参数如果不传,会导致逻辑处理函数无线循环调用
3.第二个参数如果传递为一个空数组,那么逻辑处理函数就只能执行一次,相当于componentDidMount(组件挂载)
4.如果第二个参数不是空数组,那么在数组中的依赖变化的时候就会触发逻辑函数的调用,就像componentDidMount和componentDidUpdate组合的生命周期函数一样
5.useEffect在组件被销毁去除之前也会调用逻辑执行函数,会消除副作用,类似componentWillUnmount生命周期函数
四.常见BUG
1.逻辑执行函数循环执行
没有传递第二个参数:如果没有传递第二个参数会导致回调函数的死循环执行
在回调逻辑函数中修改依赖:如果在回调逻辑函数中修改依赖就会导致逻辑函数的不断触发,从而造成死循环
2.useEffect监测不到依赖的变化
依赖地址的值并没有改变:
const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
setA((old) => {
old.b = 'yx'
return old
})
}
useEffect(() => {
/** 当组件挂载时执行一次changeA */
changeA ()
},[])
/**当changeA执行却没有打印 a*/
useEffect(() => {
/** 执行逻辑 */
console.log(a)
},[a])
以上代码仅仅改变的只是变量a在堆中的值,并没有改变a在栈中地址值,useEffect无法监测到堆中的数据变化,所以不会触发逻辑执行,所有的引用类型都应该注意这一点
const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
setA((old) => {
const newA = {...old}
newA .b = 'yx'
return newA
})
}
useEffect(() => {
/** 当组件挂载时执行一次changeA */
changeA ()
},[])
/**当changeA执行打印 {b:'yx',c:'18'} */
useEffect(() => {
/** 执行逻辑 */
console.log(a)
},[a])
像上面这样就可以实现useEffect的逻辑执行了,newA返回的是一个新的地址。