一 介绍
useEffect是在React更新DOM之后运行一些额外的代码,也就是执行副作用操作,比如请求数据,设置订阅,手动更改React组件中的DOM等。
二 用法
useEffect(() => {
// 相当于 componentDidMount、componentDidUpdate
console.log("code");
return () => {
// 相当于 componentWillUnmount
console.log("code");
}
}, [/*依赖项*/])
useEffect中定义了一个函数和一个数组,第二个参数决定了useEffect中各部分代码执行次数。
1.依赖项的几种情况:
- 什么都不传,组件每次render之后useEffect都会调用,相当于componentDidMount和componentDidUpdate。
注意,如果useEffect里的函数涉及到状态数据的变更,那么就会导致useEffect无限循环调用。 - 传入空数组[],只会调用一次,相当于componentDidMount
- 传入一个数组,其中包括变量,只有当变量变化时,useEffect才会执行
注意:
其实对于函数式组件而言不存在生命周期,把class组件的生命周期概念搬过来对号入座只是一种辅助记忆手段。
2.return函数
如果useEffect中有监听事件或者定时器等,需要在return中关闭对应的监听事件和定时器
三 注意点
1.当依赖项是引用类型时,React会对比依赖项的内存地址是否一致。只有当不一致时,useEffect才会执行。
const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
setA((old) => {
old.b = 'yx'
return old
})
}
/**当changeA执行却没有打印 a*/
useEffect(() => {
console.log(a)
},[a])
常用的修改方法就是修改引用:
const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
setA((old) => {
const newA = {
...old}
newA.b = 'yx'
return newA
})
}
/**当changeA执行打印 {b:'yx',c:'18'} */
useEffect(() => {
console.log(a)
},[a])
2.看一个useEffect的例子
import React, {
useState, useEffect } from 'react'
function App() {
const [count, setCount] = useState(0) //默认值是0
const [name, setName] = useState('张三') //默认值是0
const [size, setsize] = useState({
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
})
const onResize = () => {
setsize({
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
})
}
//操作
useEffect(() => {
document.title = count
}) //没有第二个参数就表示只要函数渲染就都执行
useEffect(() => {
//监听
window.addEventListener('resize', onResize, false)
//监听完了就考虑卸载,卸载的时候必须是return
return () => {
window.addEventListener('resize', onResize, false)
}
}, [])
//空数组里面要是什么也不填写,那他只会发生在第一次渲染后和组件卸载之前执行
// 也就是钩子函数componentDidMount 和componentWillUnMount
useEffect(() => {
console.log('count', count)
}, [count])
//只有count发生变化时候执行,和第一次渲染后以及组件卸载前执行
useEffect(() => {
document
.querySelector('#size')
.addEventListener('click', handleClick2, false)
return () => {
document
.querySelector('#size')
.removeEventListener('click', handleClick2, false)
}
})
const handleClick2 = () => {
console.log('点击了')
}
function handleClick() {
setCount(count + 1)
setName('李四')
}
return (
<div>
<span>
{
count}---{
name}
</span>
{
count % 2 === 0 ? (
<span id="size">
宽度是:{
size.width}--高度是:{
size.height}
</span>
) : (
<p id="size">
宽度是:{
size.width}--高度是:{
size.height}
</p>
)}
<button type="button" onClick={
handleClick}>
点击
</button>
</div>
)
}
export default App