React.useEffect模拟生命周期

11,291 阅读1分钟

模拟componentDidMount

useEffect(()=>{console.log('第一次渲染时调用')},[])

第二个参数为一个空数组,可以模拟componentDidMount

模拟componentDidUpdate

没有第二个参数代表监听所有的属性更新

useEffect(()=>{console.log('任意属性该改变')}) 

监听多个属性的变化需要将属性作为数组传入第二个参数。

useEffect(()=>{console.log('n变了')},[n,m]) 

模拟componentWillUnmount

通常,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源

useEffect(()=>{
	const timer = setTimeout(()=>{
    	...
    },1000)
	return()=>{
    	console.log('组件死了')
    	clearTimerout(timer)
    }
})

useEffect函数返回的函数可以表示组件死亡

自定义effect

实现componentDidUpdate。

第一版

    const [n,setN] = React.useState(0)
    const [count,setCount] = React.useState(0);
    React.useEffect(() => {
        setCount((n)=>n+1);
    },[n])
    React.useEffect(()=>{
      if(count>1){
          console.log('跟新了')
      }
    },[count])

使用一个变量count变量来保证在第一次执行的时候不做操作。

封装一下

将hook封装之后函数名必须是以use开头的

    const useUpdate=(fn,n)=>{
        const [count,setCount] = React.useState(0);
        React.useEffect(() => {
            setCount((n)=>n+1);
        },[n])
        React.useEffect(()=>{
            if(count>1){
                fn()
            }
        },[count,fn])
    }

    const [n,setN] = React.useState(0)
    useUpdate(()=>{
        console.log('跟新了')
    },n)

封装之后就可以向调用React.useEffect一样使用,不过它不支持多个属性。

    const useUpdate=(fn,n)=>{
        const [count,setCount] = React.useState(0);
        React.useEffect(() => {
            setCount((n)=>n+1);
+       },[...n])
        React.useEffect(()=>{
            if(count>1){
                fn()
            }
        },[count,fn])
    }

    const [n,setN] = React.useState(0)
    useUpdate(()=>{
        console.log('跟新了')
+   },[n])

如果将代码改为这样就可以接受多个参数,但是React会发出一个警告。因为React无法预测传入的数组大小类型等,所以还是建议使用上一种封装,我们应该尽相避免。

还有就是封装useEffect后函数模必须以use开头