React hooks之useEffect

useEffect(副作用)通过一个参数来实现模拟class组件的componentDidMount、componentWillUnmount还有componentDidUpdate这几个生命周期函数
无阻塞更新:因为他是在组件挂载之后执行操作,比如请求数据,他是在组件挂载完了以后才执行数据请求,这样就算请求失败了,页面也能正常显示,不会报错;
同一个组件可以多次使用useEffect。

第一种:第二个参数不传值

相当于是监听页面的变化,只要页面有更新,都会执行。
注意:不能在这个函数体内执行页面更新操作,否则会陷入死循环

import React, { useEffect, useRef, useState, useReducer, useMemo } from 'react';
export default function HookDemo(props) {
    let [num, setNum] = useState(0);
    useEffect(() => {
        // 这个是监听的页面的变化,只要页面有state变化就会执行,不能在这个函数体内执行页面更新操作,否则会陷入死循环。
        // 类似class组件的componentDidUpdate
        console.log('页面监听');
    });
    return (
        <div style={{ padding: 30 }}>
            <div style={{ marginTop: 30 }}>
                {/* useEffect */}
                <h2>useEffect</h2>
                <h2>你点了我{num}次了</h2>
                <button onClick={() => setNum(num + 1)}>点击</button>
            </div>
        </div>
    );
}

第二种:第二个参数传[]

表示的是它不监听页面数据的变化,只有在页面初始化和销毁之前会执行;
执行的是类似于class组件的componentDidMount和componentWillUnmount两个生命周期;

    useEffect(() => {
        // 类似componentDidMount
        console.log('初始化一下');
        return () => {
            // 类似componentWillUnmount
            console.log('什么都不监听的时候return的函数');
        };
    }, []);

第三种:第二个参数传具体的值

监听第二个参数数组内所传的值,当对应的state有更新时触发。
注意:这里的执行顺序其实不是先执行上一次useEffect return的函数,而是先正常执行下一次状态更新然后再执行上一次的effct,然后再执行,下一次的effct。因为大多数情况下,effct不会阻塞页面的更新。

    useEffect(() => {
        // 这个的执行顺序是:先执行return里的函数,再执行外部函数体内的函数,return里获取到的num未更新num前的数据。
        console.log('监听num变化');
        console.log('函数体内获取的num', num);      // 函数体内获取的num 1
        return () => {
            console.log('监听num的时候return的函数');
            console.log('return获取的num', num);        // return获取的num 0
        };
    }, [num]);

effct其实是组件输出的一部分,单次渲染范围内,effct里的props和state是保持不变的。

effects会在每次渲染后运行,并且概念上它是组件输出的一部分,可以“看到”属于某次特定渲染的props和state。就是只要组件有更新,useEffect都是作为组件输出的一部分。
在单次渲染的范围内,props和state都保持不变。
这一点上,函数式组件和class组件是不一样的,因为class组件做了处理,this.state始终是指向最新的值,而不是属于某次特定渲染的值。

    const lateInputValue = useRef(inputVal);
    useEffect(() => {
        setTimeout(() => {
            console.log(`延时获取inputval的值:${inputVal}`);       
            // 延时获取inputval的值:2  延时获取inputval的值:23 延时获取inputval的值:234
        }, 3000);
        // 用ref可以打破这种单次独立渲染,因为ref始终指向的是最新的inpuval的值,所以在定时器范围内更改了inputval的值,那么ref获取到的就是最新的状态值。
        lateInputValue.current = inputVal;
        setTimeout(() => {
            console.log(`验证一下lateInputValue是几? ${lateInputValue.current}`);      
            // 验证一下lateInputValue是几?  234 验证一下lateInputValue是几? 234    验证一下lateInputValue是几? 234
        }, 3000);
    }, [inputVal]);
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容