useEffect的含义:副作用钩子,用于处理组件中的副作用,用来取代生命周期函数。所谓的"副作用"就是指的是组件中状态或生命周期改变时在useEffect可监听到。
如果熟悉class组件中生命周期方法,可以将useEffect视作coponentDidMount、componentDidUpdate和componentWillUnmount的组合体。
useEffect使用的几种方式,根据第二个参数的情况而定
- 无此参数:组件的任何更新,该 useEffect 对应的返回函数和函数都执行
- 为空数组:只在componentDidMount执行一次,不监听组件的更新,
- 数组中有具体依赖:对应的依赖数据,有变化的时候,才会执行(初始不会执行)
清除 effect
通常,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源。要实现这一点,useEffect 函数需返回一个清除函数。以下就是一个事件绑定的例子:
import { useState, useEffect } from "react";
import * as ReactDOM from "react-dom";
function App() {
const [position, setPosition] = useState({x:0, y: 0})
useEffect(()=>{
console.log('点击了b')
const mouseClickHandle = (e) =>{
console.log('点击了c')
setPosition({
x: e.clientX,
y: e.clientY
})
}
document.addEventListener('click', mouseClickHandle)
// return ()=>{
// console.log('点击了d')
// document.removeEventListener('click', mouseClickHandle)
// }
})
console.log('点击了a')
return (
<>
<p>
X:{position.x}, Y: {position.y}
</p>
</>
)
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
执行点击事件,可以看到打印结果如下:
微信截图_20211207151814.png可以看到,当我第三次点击的时候,打印结果显示click事件被执行了两次,在这个示例中,意味着组件的每一次更新都会创建新的事件绑定,这很显然是不被允许的。
这个时候就需要使用清除函数,清除函数会在组件卸载前执行。另外,如果组件多次渲染(通常如此),则在执行下一个 effect 之前,上一个 effect 就已被清除。
useEffect允许返回一个函数来解决上述问题:
useEffect(()=>{
console.log('点击了b')
const mouseClickHandle = (e) =>{
console.log('点击了c')
setPosition({
x: e.clientX,
y: e.clientY
})
}
document.addEventListener('click', mouseClickHandle)
// 在此处返回一个解绑函数即可
return ()=>{
console.log('点击了d')
document.removeEventListener('click', mouseClickHandle)
}
})
console.log('点击了a')
当返回一个解绑函数后再次测试发现,在组件在执行下一个 effect 之前,上一个 effect 就已被清除(d在b之前打印可以印证这点)。
微信截图_20211207152514.png
下面再来印证上述提到的第二个参数为空数组的情况:
useEffect(()=>{
console.log('点击了b')
const mouseClickHandle = (e) =>{
console.log('点击了c')
setPosition({
x: e.clientX,
y: e.clientY
})
}
document.addEventListener('click', mouseClickHandle)
return ()=>{
console.log('点击了d')
document.removeEventListener('click', mouseClickHandle)
}
},[])
console.log('点击了a')
微信截图_20211207153514.png
可以看到,当第二个参数为空数组的时候,b和d都没有打印,说明此时useEffect并不被执行,执行的只是初始进入就绑定的事件。
网友评论