文章

Hooks 簡介

Hooks 簡介

Hooks 是 React 16.8 引入的一個功能,它允許你在函數型組件(Functional Components)中使用狀態(state)和其他 React 功能,而不需要使用類別組件(Class Components)。這使得函數型組件能夠更靈活且簡潔地實現狀態管理、生命週期操作等功能。

Hooks 的特點

  1. 完全向後兼容:你可以逐步在現有項目中引入 Hooks,而不會對現有代碼產生影響。
  2. 不會破壞類別組件:類別組件仍然可以繼續使用,但 Hooks 提供了一種更簡潔的方式來處理相同的功能。
  3. 減少複雜性:在不需要寫類別的情況下,可以實現狀態管理和副作用處理,使代碼更加直觀。

1. 使用狀態的 Hook:useState

useState 是最常見的 Hook,用於在函數型組件中添加狀態。

基本語法:

1
const [state, setState] = useState(initialState);
  • state:是當前狀態的值。
  • setState:是一個函數,用來更新狀態。
  • initialState:是狀態的初始值,可以是任意數據類型。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);  // 定義一個 count 狀態,初始值為 0

  return (
    <div>
      <p>當前計數: {count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
    </div>
  );
}

export default Counter;

在這個範例中:

  • useState(0) 初始化了一個 count 狀態,初始值為 0
  • 當按鈕被點擊時,調用 setCount 函數將 count1,從而觸發組件重新渲染。

2. 處理副作用的 Hook:useEffect

useEffect 用來在函數型組件中執行副作用操作,比如數據請求、訂閱和手動 DOM 操作。這相當於類別組件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount

基本語法:

1
2
3
4
5
6
useEffect(() => {
  // 副作用操作,例如數據請求
  return () => {
    // 可選的清理操作
  };
}, [dependencies]);
  • 副作用操作:在組件渲染後執行的操作。
  • 清理操作:用來清理之前的副作用,比如移除事件監聽器。這個函數會在組件卸載時或依賴項變化之前執行。
  • [dependencies]:依賴項數組。只有當數組中的某些值發生改變時,useEffect 內的副作用操作才會重新執行。如果不傳入依賴項,副作用會在每次渲染後執行。如果依賴項數組為空,副作用只會在掛載和卸載時執行一次。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);

    return () => clearInterval(interval); // 清除計時器,避免內存泄漏
  }, []);

  return <p>計時器: {count}</p>;
}

export default Timer;

在這個範例中:

  • useEffect 設置了一個計時器,每秒增加一次計數器。
  • return 語句返回了一個清理函數,用來在組件卸載時清除計時器,防止內存洩漏。

3. 更多常用 Hooks

除了 useStateuseEffect,React 還提供了其他有用的內建 Hooks:

useContext

useContext 用來在函數型組件中讀取上下文(context)數據,而不需要用 Context.Consumerthis.context

1
const value = useContext(MyContext);

useReducer

useReduceruseState 的替代方案,適合處理更複雜的狀態邏輯(例如管理多個相關狀態)。

1
const [state, dispatch] = useReducer(reducer, initialState);

useRef

useRef 用來存儲可以在渲染間保持不變的可變值,或直接訪問 DOM 元素。

1
const inputRef = useRef(null);

useMemouseCallback

  • useMemo 用於優化性能,避免在每次渲染時進行昂貴的計算。
  • useCallback 用於緩存函數,避免不必要的函數重新創建,適合傳遞給子組件的函數。

4. 自定義 Hooks

除了內建的 Hooks,React 允許你創建自定義 Hooks,這使得我們可以將組件邏輯進行封裝和重用。自定義 Hooks 就是一個以 “use” 開頭的普通函數,它可以使用其他 Hooks 並返回一些值。

範例:自定義 useFetch Hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      });
  }, [url]);

  return { data, loading };
}

export default useFetch;

這個自定義 useFetch Hook 封裝了數據請求邏輯,我們可以在不同的組件中重複使用它。


5. Hooks 的規則

使用 Hooks 時有兩個重要的規則:

  1. 只能在函數最頂層調用 Hooks:不要在循環、條件或嵌套函數中調用 Hooks,這是為了確保 Hooks 按照相同的順序執行。
  2. 只能在 React 函數組件或自定義 Hook 中使用 Hooks:不要在普通的 JavaScript 函數中使用 Hooks。

總結

Hooks 是 React 中強大的功能,使得我們能夠在函數型組件中使用狀態、生命週期和其他功能,並且可以更好地重用邏輯。useStateuseEffect 是最常用的 Hooks,通過它們,我們可以實現大部分狀態管理和副作用處理的需求。隨著自定義 Hooks 的引入,開發者可以將複雜邏輯進行封裝和重用,使得代碼更加清晰易讀。

本文章以 CC BY 4.0 授權