目录
参考资料
https://zh-hans.react.dev/reference/react/useEffect
useEffect
应用场景
useEffect hook用于与外部方法保持同步。
也就是说,考虑这样的场景,组件要渲染的数据不只是取决于组件内部的数据,也需要组件外部的数据,在组件内部,首先要获取外部的数据,而外部数据通常通过服务器接口等获得,存在一定的延迟。如果要等到接口数据返回,然后再渲染组件,有很大可能在页面加载时会产生一定的延迟。对于这种情况,可以把获取外部数据设计成异步操作。在组件内部,获取外部数据时,不会阻塞组件渲染,组件其他结构会正常渲染,当异步数据返回时,对渲染的结果进行更新渲染。
react提供了一个Hook函数,useEffect,来达成这种效果。
use使用 effect效果,可以看做页面渲染返回之后,useEffect可以拿到这个结果,然后使用。
副作用
由于useEffect内部一般调用外部方法,也就是外部方法影响内部,有时也把这些外部方法叫做副作用。useEffect可以看成在特定的时间使用副作用。
触发时机
useEffect在组件渲染好之后触发。useEffect是异步的。
它会在组件首次渲染、组件更新、组件销毁时触发。也就是说,useEffect会在每一次渲染完成后执行。
有时,如果确定某些状态的改变才需要useEffect触发,而不是每次不论什么数据改变引发渲染时都触发,可以给useEffect设置依赖项,当依赖项中的数据更新时,useEffect才会更新,依赖项在useEffect第二个参数里配置,如果不进行配置,那么默认useEffect会在每一次渲染后执行。
基础用法
useEffect可以接收两个参数,第一个参数是回调函数,每次useEffect触发时会调用这个函数。第二个参数是依赖项数组。如果依赖项数组是空数组,那么useEffect会在初次渲染时执行一次,然后不论页面如何渲染,都不再执行。
import {useState,useEffect} from 'react'
export default function App() {
const [count,setCount] = useState(0)
const [page,setPage] = useState(1)
useEffect(
()=>{
console.log(document.getElementsByTagName('h1'))
console.log(count,page)
},[page]
)
console.log('@@')
return (
<div>
<h1 onClick={()=>{setCount(count+1)}}>
{count}
</h1>
<button onClick={()=>{setPage(page+1)}}>nextPage</button>
</div>
)
}
清除函数
useEffect回调函数的返回值。这个返回值必须是一个函数,这个函数被称为清除函数。如果不是函数,会引发报错,也就是说,如果给回调函数添加async,这也会导致报错,因为async函数默认返回Promise,如果确实要使用异步调用,可以在useEffect内部定义一个函数,这个函数是async函数,然后再在useEffect内部调用这个函数。
如果在useEffect内部,调用了定时器、添加了监听事件、链接了数据库,可以在清除函数内部进行清除。
如果在每次useEffect调用时,不进行清除,由于useEffect内部操作是独立的,每次调用都会重新执行一遍,并不会产生覆盖,那么每次调用时都会创建一次链接,造成多个链接。
清除函数的执行时机
清除函数在useEffect下一次调用之前调用。拿到的是上一次useEffect的DOM状态。
清除函数中是上一次useEffect的状态:
在useEffect中,清除函数会被先执行,此时清除函数中,状态还是上一次useEffect执行时的状态。
import {useState,useEffect} from 'react'
export default function App() {
const [count,setCount] = useState(0)
const [page,setPage] = useState(1)
useEffect(
()=>{
return ()=>{
console.log(count)
}
},
)
return (
<div>
<h1 >
{count}
</h1>
<button onClick={()=>{setCount(count+1)}}>nextPage</button>
</div>
)
}
‘
清除函数清除定时器:
import {useState,useEffect} from 'react'
export default function App() {
const [count,setCount] = useState(0)
const [page,setPage] = useState(1)
useEffect(
()=>{
console.log(document.getElementsByTagName('h1'))
console.log(count,page)
let timer = setInterval(()=>{
setCount((count)=>{return count+1})
},1000)
return ()=>{
clearInterval(timer)
}
},[page]
)
console.log('@@')
return (
<div>
<h1 onClick={()=>{setCount(count+1)}}>
{count}
</h1>
<button onClick={()=>{setPage(page+1)}}>nextPage</button>
</div>
)
}