首页 > 其他分享 >React - 13 Hooks组件之useEffect

React - 13 Hooks组件之useEffect

时间:2023-06-30 21:02:21浏览次数:42  
标签:13 console log Hooks React callback num Demo useEffect

1.useEffect

import React, { useState, useEffect } from "react";
import { Button } from 'antd';
import './Demo.less';

/*
 useEffect:在函数组件中,使用生命周期函数
   useEffect(callback):没设置依赖
     + 第一次渲染完毕后,执行callback,等价于 componentDidMount
     + 在组件每一次更新完毕后,也会执行callback,等价于 componentDidUpdate

   useEffect(callback,[]):设置了,但是无依赖
     + 只有第一次渲染完毕后,才会执行callback,每一次视图更新完毕后,callback不再执行
     + 类似于 componentDidMount

   useEffect(callback,[依赖的状态(多个状态)]):
     + 第一次渲染完毕会执行callback
     + 当依赖的状态值(或者多个依赖状态中的一个)发生改变,也会触发callback执行
     + 但是依赖的状态如果没有变化,在组件更新的时候,callback是不会执行的

   useEffect(()=>{
      return ()=>{
        // 返回的小函数,会在组件释放的时候执行
        // 如果组件更新,会把上一次返回的小函数执行「可以“理解为”上一次渲染的组件释放了」
      };
   });
 */
const Demo = function Demo() {
    let [num, setNum] = useState(0),
        [x, setX] = useState(100);

    useEffect(() => {
        // 获取最新的状态值
        console.log('@1', num);
    });
    
    useEffect(() => {
        console.log('@2', num);
    }, []);

    useEffect(() => {
        console.log('@3', num);
    }, [num]);

    useEffect(() => {
        return () => {
            // 获取的是上一次的状态值
            console.log('@4', num);
        };
    }); // 这里传[num]和不传都一样

    const handle = () => {
        setNum(num + 1);
    };
    return <div className="demo">
        <span className="num">{num}</span>
        <Button type="primary"
            size="small"
            onClick={handle}>
            新增
        </Button>
    </div>;
};

export default Demo;

执行原理

React - 13 Hooks组件之useEffect_react

2.useEffect和useLayoutEffect的细节

①不能把useEffect放在条件判断中,可以把条件判断放在useEffect的回调函数中

②useEffect的回调函数要么不返回值,要么只能返回一个函数

③经过async修饰之后,即使不写返回,默认返回Promise实例

import React, { useState, useEffect } from "react";
import { Button } from 'antd';
import './Demo.less';

// 模拟从服务器异步获取数据
const queryData = () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve([10, 20, 30]);
        }, 1000);
    });
};

const Demo = function Demo() {
    let [num, setNum] = useState(0);

    /* // useEffect必须在函数的最外层上下文中调用,不能把其嵌入到条件判断、循环等操作语句中
    if (num > 5) {
        useEffect(() => {
            console.log('OK');
        });
    } */
    useEffect(() => {
        if (num > 5) {
            console.log('OK');
        }
    }, [num]);

    // 第一次渲染完毕后,从服务器异步获取数据
    /* // useEffect如果设置返回值,则返回值必须是一个函数「代表组件销毁时触发」;下面案例中,callback经过async的修饰,返回的是一个promise实例,不符合要求!!
    useEffect(async () => {
        let data = await queryData();
        console.log('成功:', data);
    }, []); */
    /* useEffect(() => {
        queryData()
            .then(data => {
                console.log('成功:', data);
            });
    }, []); */
    useEffect(() => {
        const next = async () => {
            let data = await queryData();
            console.log('成功:', data);
        };
        next();
    }, []);

    const handle = () => {
        setNum(num + 1);
    };
    return <div className="demo">
        <span className="num">{num}</span>
        <Button type="primary"
            size="small"
            onClick={handle}>
            新增
        </Button>
    </div>;
};

export default Demo;

3.useEffect与useLayoutEffect的区别

React - 13 Hooks组件之useEffect_react_02

useLayoutEffect先于useEffect

React - 13 Hooks组件之useEffect_react_03

两者都可以获取dom,

React - 13 Hooks组件之useEffect_react_04

import React, { useState, useEffect, useLayoutEffect } from "react";
import { Button } from 'antd';
import './Demo.less';

const Demo = function Demo() {
    // console.log('RENDER');
    let [num, setNum] = useState(0);

    /* useLayoutEffect(() => {
        if (num === 0) {
            setNum(10);
        }
    }, [num]); */

    /* 
     useLayoutEffect会阻塞浏览器渲染真实DOM,优先执行Effect链表中的callback;
     useEffect不会阻塞浏览器渲染真实DOM,在渲染真实DOM的同时,去执行Effect链表中的callback;
       + useLayoutEffect设置的callback要优先于useEffect去执行!!
       + 在两者设置的callback中,依然可以获取DOM元素「原因:真实DOM对象已经创建了,区别只是浏览器是否渲染」
       + 如果在callback函数中又修改了状态值「视图又要更新」
         + useEffect:浏览器肯定是把第一次的真实已经绘制了,再去渲染第二次真实DOM
         + useLayoutEffect:浏览器是把两次真实DOM的渲染,合并在一起渲染的

     视图更新的步骤:
       第一步:基于babel-preset-react-app把JSX编译为createElement格式
       第二步:把createElement执行,创建出virtualDOM
       第三步:基于root.render方法把virtualDOM变为真实DOM对象「DOM-DIFF」
         useLayoutEffect阻塞第四步操作,先去执行Effect链表中的方法「同步操作」
         useEffect第四步操作和Effect链表中的方法执行,是同时进行的「异步操作」
       第四步:浏览器渲染和绘制真实DOM对象
    */
    useLayoutEffect(() => {
        console.log('useLayoutEffect'); //第一个输出
    }, [num]);
    useEffect(() => {
        console.log('useEffect'); //第二个输出
    }, [num]);

    return <div className="demo"
        style={{
            backgroundColor: num === 0 ? 'red' : 'green'
        }}>
        <span className="num">{num}</span>
        <Button type="primary" size="small"
            onClick={() => {
                setNum(0);
            }}>
            新增
        </Button>
    </div>;
};

export default Demo;


标签:13,console,log,Hooks,React,callback,num,Demo,useEffect
From: https://blog.51cto.com/u_12207234/6593754

相关文章

  • 无意间做了个 web 版的 JVM 监控端前后端分离 React+Spring Boot
    本来就是为了更多的了解JMX,第一步就想把所有的MBean和属性都展示出来,开始在控制台输出,但是效果不好,内容太多太长,不够直观,然后就加了个web端的树形结构。然后做着做着突然发现,再稍微改改就能当个web版的简易监控端用了。此工具只在hotspotJVM8环境下测试过。可支持查看......
  • System.Data.SqlClient.SqlException (0x80131904): Invalid object name 'Person'.
    @@abpMicrosoft.Data.SqlClient.SqlException(0x80131904):Invalidobjectname 请求接口报错:System.Data.SqlClient.SqlException(0x80131904):Invalidobjectname'Person'.无效的名称:Person数据库没有这个表,或者这个字段处理;检查数据库是否有改表或该字段......
  • Vue3 reactive 操作数组 响应性(数组变了,但页面显示没变)问题
    问题代码:tableTemplates:Array<HkTaskTemplateEntity>=reactive([]);//删除方法的一部分,根据templateId删除数组数据this.tableTemplates=this.tableTemplates.filter(item=>templateId!==item.templateId);删除后tableTemplates数组中对象减少,但vue页面显示数据......
  • 【雕爷学编程】Arduino动手做(139)---E18-D80避障传感器模块
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • React - 12 Hooks组件之useState
    1.hooks组件本质是函数组件2.useState①基础用法importReact,{useState}from"react";import{Button}from'antd';/*useState:ReactHook函数之一,目的是在函数组件中使用状态,并且后期基于状态的修改,可以让组件更新let[num,setNum]=useState(initialValue);......
  • 【雕爷学编程】Arduino动手做(138)---64位WS2812点阵屏模块
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • Python报错 | PermissionError: [Errno 13] Permission denied: 'xxx'
    报错信息使用python对模型进行输出文件的过程中,报如下错误:PermissionError:[Errno13]Permissiondenied:'xxx'错误原因报错翻译过来是:权限错误:[errno13]权限被拒绝:错误产生的原因是文件无法打开,可能产生的原因是文件找不到,或者被占用,或者无权限访问,或者打开的不是文......
  • react保姆级搭建新项目
    此文主要以ts+vite+router6+antd快速搭建一个react项目,适用于初学者一、项目搭建采用pnpm,个人感觉比npm和yarn好用npmipnpm-g采用vite方式,根据选择react-tspnpmcreatevite1.1修改初始结构,删除多余文件1.2修改vite.config配置文件配置别名vite.config:import{defineC......
  • 「ARC133E」Cyclic Medians 题解
    本文网址:https://www.cnblogs.com/zsc985246/p/17513317.html,转载请注明出处。传送门「ARC133E」CyclicMedians题目大意给定\(n,m,V,A\),你需要计算所有长为\(n\)、值域为\([1,V]\)的整数序列\(x\)和长为\(m\)、值域为\([1,V]\)的整数序列\(y\)形成的序列对\((x_......
  • 绍兴高防BGP服务器-游戏专用高频服务器-203.135.98.X
    绍兴高防BGP服务器-游戏专用高频服务器绍兴高防BGP服务器是一种专门为游戏行业设计的高频服务器。在现代社会中,游戏行业的发展迅猛,吸引了大量的玩家加入其中。玩家对游戏的需求不断增加,对服务器的性能要求也越来越高。因此,绍兴高防BGP服务器应运而生,以满足游戏行业对服务器的需求......