持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
前言
上一篇文章讲了react hook的useState, 这篇文章再来看看其它的hook,useEffect。
useEffect
这个是叫副作用 hook,主要是用来解决副作用的逻辑,比如修改dom,异步请求等等。 因为函数组件原本设计是纯函数,并不计划执行这些操作。
这些逻辑在class组件基本上是在componentDidMount生命周期执行的,然后就可以把这些逻辑迁移到这里。
但是不仅仅如此。
其实在componentDidUpdate生命周期和componentWillUnmount生命周期都会执行。
它其实相当于componentDidMount,componentDidUpdate,componentWillUnmount的合并。
这样是不是很方便?
它接受2个参数,第一个就是要执行的副作用的函数,没有参数,第二个是指定哪些state数据更新时才会执行useEffect, 数组形式,里面是对应的state的key。
如果不填的时候,则所有数据更新时都会执行useEffect。如果填空数组,则不会在数据更新时执行(相当于componentDidUpdate生命周期不会执行)
然后如果组件被销毁时,如果想把useEffect里的函数清除掉,比如setTimeout,要clearTimeout掉。
这时你可以在第一个函数里返回清除函数,里面是清除的逻辑。
例子
下面通过例子来学习下useEffect:
function HelloWorld () {
const [text, setText] = useState('hello world')
useEffect(() => {
console.log('执行 useEffect')
// 模拟异步请求
const timer = setInterval(() => {
console.log('timer')
}, 1000)
})
return (
<div onClick={() => { setText('答案cp3') }}>{text}</div>
)
}
可以看到一进入页面会打印一次执行 useEffect(相当于componentDidMount)
然后就一直执行setInterval
然后点击按钮,会重新打印执行 useEffect(相当于componentDidUpdate)。
然后我们来模拟componentWillUnmount生命周期的代码,第一个函数需要返回清除函数
代码如下:
function HelloWorld () {
const [text, setText] = useState('hello world')
useEffect(() => {
console.log('执行 useEffect')
// 模拟异步请求
const timer = setInterval(() => {
console.log('timer')
}, 1000)
return () => {
console.log('清除 useEffect')
clearInterval(timer)
}
})
return (
<div onClick={() => { setText('答案cp3') }}>{text}</div>
)
}
function App () {
const [show, setShow] = useState(true)
return (
<div>
<button onClick={() => setShow(false)}>show:{show.toString()}</button>
{show && <HelloWorld />}
</div>
)
}
页面会执行 useEffect,然后点击button,会把show设置为false,然后就会执行useEffect的清除函数(相当于componentWillUnmount)。
然后timer就不会再打印了。
下面再来看看useEffect的第二个参数的用法。不传就是监听所有数据的更新,传了就是只监听对应数据的更新。
function HelloWorld () {
const [text1, setText1] = useState('text1')
const [text2, setText2] = useState('text2')
useEffect(() => {
console.log('执行 useEffect')
}, [text2])
return (
<div>
<div onClick={() => { setText1('text1更新') }}>{text1}</div>
<div onClick={() => { setText2('text2更新') }}>{text2}</div>
</div>
)
}
执行后就会发现,点击第一个按钮不会重新执行useEffect,点击第二个按钮才会,因为它监听的是text2。