useEffect被称为副作用钩子,可以让你在函数式组件中执行副作用操作
useEffect支持两个参数
第一个参数为一个函数,表示副作用效应函数,默认情况下它会在第一次和每次更新之后都会执行。
useEffect(() => {
console.log('加载')
})
// 如果没有第二个参数,副效应函数会在每次渲染时都会执行
第二个参数是一个数组,为第一个参数(函数)的依赖项,当数组中的变量发生变化时就会执行副效应函数
useEffect(() => {
console.log('加载')
},[])
// 一般如果没有依赖项,我们会添加一个空数组,这样就会在组件加载完成后只执行一次
const [count, setCount] = useState(0);
useEffect(() => {
console.log('count')
}, [count])
// 如果想在count变化时执行副效应函数,那么把该变量放在第二个数组参数中即可
如果我们依赖多个变量的变化来执行副效应函数,一般不建议写在一起,如:
const [id, setId] = useState(1);
const [name, setName] = useState('xiaoming');
useEffect(() => {
console.log('执行了')
},[count, number])
// 这种写法下,如果count和number都改变的话会导致副效应函数执行多次,可能会带来一些未知问题
所以当需要多个依赖项的时候我们可以分开写useEffect,或将我们的依赖项合并如:
const [info, setInfo] = useState({id: 1, name: '小明'});
useEffect(() => {
console.log('执行了')
}, [info])
// 合并依赖项,此时只需要依赖合并后的变量
那么如果我们需要当name和id同时变化时才去执行副效应函数,该如何做呢,此时需要将两个变量都放到依赖项中,我们需要在副效应函数的内部增加一些判断是否执行副效应函数中的逻辑代码
const [id, setId] = useState(1);
const [name, setName] = useState('小红');
// useRef ==> 另一种hook,此时可以用它来存储id,name的初始值
const userInfoRef = useRef({id, name})
useEffec(() => {
const {id: preId, name: preName} = userInfoRef;
// 当前的id和name都不等于初始值才执行
if (id !== preId && name !== preName) {
console.log('执行了');
// 执行后需要把改变后的id和name放到userInfoRef中存储
userInfoRef.current = {id, name};
}
}, [id, name])
我们都知道类组件中的生命周期钩子componentWillUnmount,是当组件卸载时执行一些操作,useEffect也是可以满足的
useEffect(() => {
const timer = setTimeout(()=>{
console.log('卸载')
}, 1000)
// 我们需要在组件卸载时清理定时器,useEffect允许返回一个函数,会在函数卸载时,执行该函数
return () => {
// 我们可以再组件卸载时清理定时器
clearTimeout(timer)
}
},[])