先回忆一下:
class组件
中的componentDidUpdate生命周期是初次渲染完后,当接收的props,state改变时或者this.forceUpdate()就会调用函数组件
中的useEffect可以看做 componentDidMount,componentDidUpdate
和componentWillUnmount 这三个函数的组合
useEffect( ()=>{ } )
只有
第一个参数的时候
此时相当于componentDidMount + componentDidUpdate钩子的组合,初次渲染并且状态改变时都会触发
需求:
那么我想通过useEffect模拟componentDidUpdate生命周期
,而去掉初次渲染时调用的 componentDidMount
useRef实现
因为初次渲染只会发生一次,可以使用useRef立一个flag解决:
const mounting = useRef(true);
useEffect(() => {
if (mounting.current) {
console.log("初次")
mounting.current = false;
return
}
console.log("DidUpdated")
});
useState实现的弊端:
需要注意的是:这个flag不能通过useState去定义
,否则setFlag(false)
改变状态后,相当于会立马触发一次ComponentDidUpdated钩子
const [Flag, setFlag] = useState(true)
uesEffect(() => {
if (Flag) {
setFlag(false)
return
}
})
普通变量实现的问题:
应该有人像我一样想过使用普通变量let flag = true
去做标识吧?
代码如下:
import React, {
useEffect,useState} from 'react'
import {
MyContext } from './Reducer.js'
export default () => {
let [num,setNum] = useState(0)
let flag = true
useEffect(()=>{
if(flag){
console.log("初次渲染")
flag = false
return
}
console.log("componentDidUpdate")
})
return (
<>
<button onClick={
()=>{
setNum(num+1) }}>按钮{
num}</button>
</>
)
}
这样是不行的,可以发现一旦调用了setNum()更新了状态,整个函数组件都会被重新调用,也就意味着普通变量flag会重新被初始化为true
,一直会走if的逻辑