iT邦幫忙

2021 iThome 鐵人賽

DAY 3
1
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 3

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)


上一篇
Day2-React Hook 篇-認識 useState
下一篇
Day4-React Hook 篇-認識 useRef & useImperativeHandle
系列文
用30天更加認識 React.js 這個好朋友32

尚未有邦友留言

立即登入留言