文章

useContext Hook

useContext Hook

在 React 中,useContext Hook 用來方便地訪問和使用Context API,以便在組件樹中共享狀態和數據,而不需要逐層傳遞 props。


1. Context API 簡介

Context API 是 React 提供的一個工具,讓我們可以在不手動傳遞 props 的情況下,將數據或狀態在組件樹中進行共享。它適合在多個組件之間共享狀態,比如主題顏色、登錄狀態、語言設置等全局狀態。

  • Context 提供者 (Provider):提供 Context 值的組件。
  • Context 消費者 (Consumer):使用 Context 值的組件。
  • useContext:一個 Hook,用來直接消費 Context,無需使用 Consumer

2. 使用 useContext 的步驟

(1) 創建 Context

首先,我們需要使用 React.createContext() 來創建一個 Context 對象。這個對象包含了 Provider 組件,並且它可以被其他組件訂閱。

1
2
3
4
import React, { createContext } from 'react';

// 創建 Context
const ThemeContext = createContext();

(2) 提供 Context 值

接著,我們使用 ThemeContext.Provider 包裹那些需要共享這些數據的組件,並將值通過 value 屬性傳遞給 Provider。

1
2
3
4
5
6
7
function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

在這個例子中,我們將 value="dark" 提供給 ThemeContext.Provider,使得 Toolbar 和它的子組件都可以訪問這個值。

(3) 消費 Context 值

在需要使用 Context 值的組件中,我們可以通過 useContext Hook 直接訪問該值,而無需使用 props 傳遞:

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

function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext); // 使用 useContext 來消費 Context
  return <button style=>Themed Button</button>;
}

在這裡,ThemedButton 通過 useContext 獲取 ThemeContext 中的值,並根據這個值設置按鈕的背景顏色。


3. 完整範例:主題切換

我們可以使用 useContextContext API 來實現主題切換的功能。

(1) 創建主題 Context

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

// 創建主題 Context
const ThemeContext = createContext();

function App() {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value=Jekyll::Drops::ThemeDrop>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

在這裡,我們定義了 ThemeContext,並通過 ProviderthemetoggleTheme 傳遞給整個組件樹。

(2) 使用 useContext 消費主題值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const { theme, toggleTheme } = useContext(ThemeContext); // 從 Context 中提取 theme 和 toggleTheme

  return (
    <button
      style=
      onClick={toggleTheme}
    >
      切換主題
    </button>
  );
}

在這個範例中,ThemedButton 通過 useContext 獲取當前主題和切換主題的函數,並根據主題狀態設置按鈕樣式和切換按鈕功能。


4. useContext 的優勢

相比傳統的 Consumer API,useContext Hook 有以下優勢:

  1. 語法簡潔useContext 讓我們不必嵌套 Consumer 組件,從而使代碼更加簡潔和易於閱讀。
  2. 靈活使用:可以在任何函數組件中使用,不必依賴於類組件。
  3. 即時訪問:無需逐層傳遞 props,組件可以即時訪問上層提供的 Context 值。

5. 適用場景

  • 全局狀態管理:如主題、語言、用戶身份信息等需要在應用的多個地方使用的數據。
  • 跨層級數據共享:當數據需要被許多不同層級的組件使用時,useContext 可以避免逐層傳遞 props 的繁瑣操作。
  • 狀態切換和控制:像主題切換、登錄狀態等狀態控制都可以使用 useContext 來實現。

總結

useContext 是 React 中用來消費 Context 的便捷工具。它讓我們可以在函數組件中輕鬆地共享和使用全局數據,避免傳遞 props 的繁瑣操作。使用 useContext 搭配 Context API 可以有效地管理應用中的全局狀態,使代碼更加簡潔和易於維護。

本文章以 CC BY 4.0 授權