[ Day 16 ] React Hooks 中的 useEffect

https://ithelp.ithome.com.tw/upload/images/20210926/20134153h2N6P2AYml.png
昨天介绍了在 Function Component 中该如何操作 state 的方法(附上传送门),今天这篇要来为大家介绍的就是第二个较常用到的 React Hooks : useEffect() :实现在 Function Component 中操作生命周期的方法。


useEffect()

整合了原本 Class function 中的生命周期: componentDidMountcomponentDidUpdatecomponentWillUnmount 等三个方法,并用来处理 Function Component 中的 side effect 。

所以白话文来说, useEffect() 这个 Hook 可以让我们在 Function Component 中操作某些比较常使用到的生命周期方法。
不过关於最後一段说明中的 side effect 指的是什麽呢?

Side Effect

简称 Effect , 除了函式内所回传的值或是执行之外,有可能会影响甚至是改变到其他状态的情形。

官网中所提到的 side effect 范例就包含了:

  1. AJAX 非同步的资料取得
  2. 设定监听事件
  3. 手动更改 Component 中的 DOM

备注:关於 Side Effect 更详细的介绍可以操考这篇: Day 12: ES6篇: Side Effects(副作用)与Pure Functions(纯粹函式),里面有更完整的说明和补充唷!

那关於 useEffect() 这个 Hook 要怎麽样在 Function Component 中来实现上述提及的三种生命周期的方法呢?


useEffect() 应用范例

改写 Class Component 中的生命周期

先从官网的范例当中一起来看在 Class Component 中撰写生命周期的方式:

// 建立一个 Class Component <Example>
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

延续前几天的计数器范例,这边是采用 Class Component 的生命周期 componentDidMount()componentDidUpdate() 两种方法。当元件挂载於 DOM 上之後就会做第一次的网站标题渲染,之後只要监听到点击事件之後就会触发 count 变数 +1 并重新渲染网站标题。其实我们是希望它在每次的渲染後再次执行一样的内容,但是在 Class Component 中没有这样的方法,所以我们才会撰写一样的操作内容在两个不同的生命周期当中。

备注:关於浏览器 document.title 这个 API 可以参考这个网站的介绍。

如果依照原本 Class Component 的写法你就会发现我们会在不同的生命周期去做一样的事情,那如果我们改用 React Hooks 的话会有怎样的结果呢?

改用 useEffect() 撰写

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

在 Function Component 中使用 useEffect() 方法,并在该方法内直接对元件操作 Render 後的行为。意思就是当该元件初次挂载并执行渲染时触发一次 Hook 方法,或是在 state 中的资料有变化时也会再触发一次该方法。

所以我们其实可以这样来解读 useEffect() 这个 Hook :

useEffect(() => {
    /* 操作 componentDidMount() 和 componentDidUpdate */
});

不过透过上述范例我们只有应用到了两个生命周期而已,另外一个方法要怎麽应用呢?这时候我们就要来看 useEffect() 这个方法的第二个参数了。


useEffect() 的第二个参数

在上面范例我们只有应用到该 Hook 的第一个参数(也就是一个函式)。如果我们在该函式中 return 一个值且带入一个函式时,我们就能使用到生命周期的 componentWillUnmount 的方法了,不过在这边要记得加上 useEffect()第二个参数:阵列

在该阵列中加入变数後,当该变数的值产生改变时便会再次触发 useEffect() 函示。

所以我们可以在有使用到第二个参数的 useEffect() 中这样理解该函式:

useEffect(() => {
  /* 操作 componentDidMount() */
  return() => {
  /* 操作 componentWillUnmount() */
  }
}, []); 

在第二个参数的阵列中,如果没有赋予任何变数的值(等同空阵列)的话,就代表不会有任何值的变动导致该 Hook 再次被触发。因此就能够在最後函式所 return 回来的内容中撰写等同於 componentWillUnmount 的生命周期内容。

不过对於第二个参数的使用与否就会导致 useEffect() 这个 Hook 所操作的生命周期函式不同,因此在同一个 Function Component 中我们可以使用多个 useEffect() 来操作不同的变数


那今天对於 useEffect 的使用介绍就先告一个段落了!意外发现在这个章节花了比较多的时间去了解这个 Hook 的使用方式还有一些要注意的特性。
其实关於这个 Hooks Function 还有许多细节跟其他不同的用法,下面整理前辈大大们的文章给大家参考:

明天要开始为大家介绍 React 中的监听事件了,可以来期待一下唷!
那我们就下篇见ʘ‿ʘ


<<:  [Day16] 第十六章-Skill的API 服务建构 (migration,route,controller,model)

>>:  [Day23] 运用 VS Code 组合键加快编辑速度 - 操作介面篇

Day 26 测试 React 元件:使用 React Testing Library 体验 Test Driven Development (TDD) - 6

前面几天我们已经用 TDD 的方式完成了 <Editor /> 元件,但不要忘了 TDD...

javascript流程控制-判断式1

现在来介绍if判断式跟else判断式 ...

Day12 虚拟记忆体的介绍

前言 前几天都在讲实体记忆体(physical memory)该如何分配,但是在有越来越多行程同时运...

Day20:今天我们来聊一下如何使用bettercap工具来拦截 HTTP 流量

攻击者可以使用session hijacking来发起各种攻击,例如中间人(MITM)攻击。 在MI...

Sudoku Solution Validator

今日kata 原始题目如下:(4kyu) Write a function validSolutio...