一,useEffect描述

我们知道,react 的函数组件里面没有生命周期的,也没有 state,没有 state 可以用 useState 来替代,那么生命周期呢?

useEffectreact v16.8 新引入的特性。我们可以把 useEffect hook 看作是componentDidMount、componentDidUpdate、componentWillUnmounrt三个生命周期的组合。可以让你在函数式组件中执行一些副作用操作;

一般副作用操作有:

  1. 发送ajax请求
  2. 设置订阅 / 启动定时器
  3. 手动更改真实DOM

二,它的执行时机

可以看做这三个生命周期函数的组合,也就是在这三个时候会执行

componentDidMount(组件已经挂载)

componentDidUpdate(组件已经更新)

componentWillUnmount(组件即将卸载)

三,useEffect分情况使用

useEffect()有两个参数:第一个参数是要执行的回调函数,第二个参数是一个依赖项数组数组(根据需求第二个参数可选是否填写),根据数组里的变量是否变化决定是否执行函数;

先看下面简单的案例 ,下面会分情况讨论:

useEffect.js

import React, { useState, useEffect, useRef } from "react";

// 类型约定
interface interList {
  id: number | string; // 类型可能是number也可能是string
  text: string;
  done: boolean;
}
// 渲染数据
const myList: Array<interList> = [
  { id: 0, text: "参观卡夫卡博物馆", done: true },
  { id: 1, text: "看木偶戏", done: true },
  { id: 2, text: "打卡列侬墙", done: true }
];

const UseEffect: React.FC = (props: any) => {
  let [num, setNum] = useState(100);
  let [useInfo, SetUserInfo] = useState(myList);

   // 0,什么都不传 就是监听所有数据的变化
   useEffect(() => {
    console.log("我改变了-all");
  }); 

  // 1,此处相当于 componentDidUpdate生命周期 组件已经更新完成
  useEffect(() => {
    console.log("我改变了");
  }, [num]); // 只监听num的变化,useInfo的变化不会被监听到

  // 2,此处相当于componentDidMount生命周期 组件已经挂载完成
  useEffect(() => {
    console.log("componentDidMount");
    console.log("可以拿到num的值:", num);
  }, []);

  // 3,此处相当于 componentWillUnmount生命周期 组件即将卸载
  useEffect(() => {
    // 返回一个回调函数
    return () => {
      console.log("组件将要卸载了");
    };
  }, []);

  // 其实传不传空数组或不是空数组,useEffect函数里面的回调都会执行一次,也就是说componentWillUnmount这个生命周期页面进来就会执行
  // useEffect 这个hoosk也是可以写多个的,尽量不同的处理写在不同useEffect里面

  // 点击改变用户信息
  const change = () => {
    // react 建议不要更改原数组 返回一个数组的拷贝
    const newList = [...useInfo, { id: 3, text: "优菈", done: false }];
    SetUserInfo(newList);
  };

  // 点击加一
  const add = () => {
    setNum(++num);
  };

  const lis = useInfo.map((item, index) => {
    return (
      <li key={index}>
        {index}:{item.text}
      </li>
    );
  });

  return (
    <>
      <div>
        <h3>userEffect 副作用hooks函数</h3>
        <br />
        <button onClick={add}>点击加一</button>
        <p>{num}</p>
        <br />
        <button onClick={change}>改变用户信息</button>
        <ul>{lis}</ul>
      </div>
    </>
  );
};
export default UseEffect;

效果图:
在这里插入图片描述

上面代码实现的效果很简单,两个按钮分别改变各自数据的状态,状态的改变会触发 useEffect函数的执行,第二个参数的传参影响着此函数的变化,所以下面进行分情况讨论:

1,不写第二个参数 说明监测所有state,其中一个变化就会触发此函数

若不写第二个参数,函数操作每次都会执行 useEffect(method)监测所有state,相当于 componentDidUpdate生命周期 - 组件已经更新完成。

   import {useEffect } from "react";
   useEffect(() => {
    console.log("我改变了-all");
  }); // 监听所有数据的变化

2,第二个参数如果是[]空数组,说明谁也不监测

第二个参数如果是[]空数组,说明谁也不监测,此时useEffect回调函数的作用就相当于
componentDidMount生命周期 - 组件已经挂载完成;

  // 2,此处相当于componentDidMount生命周期 组件已经挂载完成
  useEffect(() => {
    console.log("componentDidMount");
    console.log("可以拿到num的值:", num);
  }, []);

3,第二个参数如果只传需要监测的state,那只会根据此状态来执行函数

如果第二个参数中的数组只传了 num ,说明只有 num改变时,才会触发此useEffect回调函数,相当于对此数据的监听。

  // 1,此处相当于 componentDidUpdate生命周期 组件已经更新完成
  useEffect(() => {
    console.log("num改变了");
  }, [num]); // 只监听num的变化

当然数组里面也可以写多个([num,userInfo]),同时监听多个数据的变化。

4,useEffect 里面return一个回调函数,相当于组件即将卸载的声明周期

这句话什么意思呢?
通常,组件是有卸载的生命周期的,使用useEffect 函数只需在里面return一个回调函数,这个回调函数就相当于componentWillUnmount 声明周期,可以在里面清除创建的订阅或计时器 ID 等资源。

  // 3,此处相当于 componentWillUnmount生命周期 组件即将卸载
  useEffect(() => {
    // 返回一个回调函数
    return () => {
      console.log("组件将要卸载了");
    };
  }, []);

这里传了空数组说明我不想监听数据的变化,只想在卸载组件的时候执行该逻辑;

5,注意

其实第二个传不传空数组或不是空数组,useEffect函数里面的回调都会执行一次,也就是说页面进来就会自动执行componentDidMount这个生命周期;

useEffect函数 这个hoosk也是可以写多个的,尽量不同的业务处理写在不同useEffect里面;

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐