Day3-React Hook 篇-认识 useEffect

今天要介绍的是常用的 hook,useEffect。

功用

处理各种的 side effect,针对渲染出来的网页後进行操作产生的影响就是 side effect。

资料 fetch、事件监听、setInterval、clearInterval、或手动改变 React component 中的 DOM 都是 side effect 的范例。

另外 React 官网有提到: 如果您熟悉 React 生命周期方法,则可以将 useEffect Hook 视为componentDidMount,componentDidUpdate 和 componentWillUnmount 的组合。

语法

useEffect(() => {
  // do ssomething...
}, [])

useEffect 第一个参数是一个 callback function,第二个参数是一个 dependency array,用来控制 useEffect 呼叫时机

  1. 当第二个参数是空阵列时,只有第一次 render 会呼叫 callback 函式
  2. 没有加第二个参数时,会在第一次 render 和每次元件 re-render 时呼叫
  3. 第二个参数阵列内有值时,会在第一次 render 和阵列内的元素值变更时呼叫

而 useEffect 执行时机一般如下

元件更新 → DOM 作对应改变 → 画面更新 → 执行 effect

不需加入至第二个参数阵列内的东西

  1. 设定 state 的函式(ex: setFormIsValid)
  2. JS 内建函式/API(ex: fetch(), localStorage, setTimeout 回传的物件)
  3. 巢状物件,不需加入不相关的物件属性,避免不需要的渲染
// good
const { someProperty } = someObject;
useEffect(() => {
  // 和 someProperty 相关的程序码
}, [someProperty]);

// good
useEffect(() => {
  // 和 someProperty 相关的程序码
}, [someObject.someProperty]);

// bad
useEffect(() => {
  // 和 someProperty 相关的程序码
}, [someObject]);

清除 side effect

在 useEffect 中处理 side effect,有些需要做一些後续的处理,否则会有效能问题,有些则不用。

无需清除的 Effect

包含呼叫 api、DOM 操作等

清除方式就是回传一个函式,是用来清理用的函式(cleanup),当每次元件渲染前,以及元件 unmount 时会被执行

useEffect(() => {
  // do ssomething...
  
  return () => {
    // ...cleanup
  }
}, [])

需清除的 Effect

事件监听(addEventListener、removeEventListener)、setTimeout、setInterval 等...

以下面的范例为例,若没有加上 return () => clearInterval(interval); 就点击 Unmount child component 会出现错误讯息

App.jsx

import { useState } from "react";
import Counter from "./Counter.js";

export default function App() {
  const [unmount, setUnmount] = useState(false);
  const renderDemo = () => !unmount && <Counter />;
  return (
    <div>
      <button onClick={() => setUnmount(true)}>Unmount child component</button>
      {renderDemo()}
    </div>
  );
}

Counter.jsx

import { useState, useEffect } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const interval = setInterval(function () {
      setCount((prev) => prev + 1);
    }, 1000);
    
    // 这里必须做 clearInterval 的动作,否则会出现错误讯息
    return () => clearInterval(interval);
  }, []);
  return <p>and the counter counts {count}</p>;
};

export default Counter;

程序码范例(codesandbox)


<<:  Day 02:Vue 个专案先

>>:  【3】训练前先暖身 - 学习率 Warm-up 策略

[第一只羊] 动物园派对桌游设计之迷雾森林

关於迷雾森林故事 序 很久很久以前 在森林的深山林里 有着一群喜欢开趴的动物 就是大家俗称的趴踢 ...

Day 20-重构 (Refactoring) 与接缝 (Seam) - 2 (核心技术-12)

在方法被呼叫前注入一个假物件-前言 (以工厂类别为示范) 今天接下来会探讨第三种型别,并非透过建构函...

从 RFC 规格书观点解析 OAuth 2.0

前言 OAuth2 目前一种 Web 主流的安全认证方法,是一种授权框架,资源所有者(Resourc...

认识 RxJS 的 Scheduler

今天我们来认识一下 RxJS 的 Scheduler,虽然在一般使用 RxJS 开发应用程序时几乎不...

[Day 50] 留言板後台及前台(六) - 前端显示资料

昨天我们已经把资料写进去了, 今天要开始显示留言板了, 但是首先我们需要抓使用者的图片, 所以要先在...