React useContext()深入淺出教學與最佳實務

React useContext()深入淺出教學與最佳實務

更新於 發佈於 閱讀時間約 9 分鐘

在 React 中,useContext() 是一個 Hook,用來讓你在函式元件中輕鬆地存取 context 資料,避免繁瑣的 props 傳遞。以下是一步步的教學與示例程式碼:

什麼是 Context?

Context 可以讓你在元件樹中傳遞資料,而不需要每層都用 props 傳遞。這對於全域設定(如主題、語言、認證狀態)特別有用。

建立一個 Context

首先,你需要 建立一個 Context 物件:

import React, {createContext} from 'react';

// 建立一個 Context,預設值可以是任何你想要的資料或空值
const MyContext = createContext({ user: null });
export default MyContext;

提供 Context 值

使用 Context Provider 將資料傳遞到元件樹中。所有被 Provider 包裹的子元件,都可以透過這個 Context 存取資料:

import React, { useState } from 'react';
import MyContext from './MyContext';
import Header from './Header';

function TestComponent() {
const [user, setUser] = useState({ name: 'Alice' });

return (
<MyContext.Provider value={{ user, setUser }}>
<Header />
</MyContext.Provider>
);
}
export default TestComponent;

在子元件中使用 useContext()

在子元件中,你可以使用 useContext() 來存取剛剛提供的 Context 資料,無需透過 props 傳遞:

import React, { useContext } from 'react';
import MyContext from './MyContext';

function Header() {
// 直接存取 context 中的資料
const { user } = useContext(MyContext);

return (
<header>
<h1>歡迎, {user.name}!</h1>
</header>
);
}

export default Header;

效果:

raw-image

使用場景與注意事項

  • 適用場景: 當多個元件需要共用某些資料時(例如使用者資料、語言設定、主題樣式)。
  • 注意事項:
    • 每次 context 的值改變時,所有使用該 context 的元件都會重新渲染,因此要避免不必要的大範圍更新。
    • 僅在真正需要跨多層元件傳遞資料時使用 context,否則簡單的 props 傳遞可能更直觀。

下面提供兩個完整的範例,一個是使用 props 傳遞兩層(父元件 → 子元件 → 孫元件),另一個則是使用 useContext 來改寫,省去中間層級的 props 傳遞。

範例1-使用 props 傳遞兩層

在這個範例中,父元件中定義了 user 狀態,並透過 props 傳遞到子元件,再由子元件傳給孫元件,孫元件可以讀取與更新 user 狀態。

Parent.js

import React, { useState } from 'react';
import Child from './Child';

function Parent() {
const [user, setUser] = useState({ name: 'Alice' });

return (
<div>
<h1>父元件</h1>
{/* 將 user 與 setUser 透過 props 傳給 Child */}
<Child user={user} setUser={setUser} />
</div>
);
}

export default Parent;

Child.js

import React from 'react';
import GrandChild from './GrandChild';

function Child(Props) {
return (
<div>
<h2>子元件</h2>
{/* 再將資料繼續傳給 GrandChild */}
<GrandChild user={Props.user} setUser={Props.setUser} />
</div>
);
}

export default Child;

GrandChild.js

import React from 'react';

function GrandChild(Props) {
const changeUser = () => {
Props.setUser({ name: 'Bob' });
};

return (
<div>
<h3>孫元件</h3>
<p>使用者名稱:{Props.user.name}</p>
<button onClick={changeUser}>更改使用者</button>
</div>
);
}

export default GrandChild;
  • 在此範例中,父元件傳遞資料到子元件,再由子元件傳遞到孫元件,這種方式隨著元件層級增加,props 傳遞會變得繁瑣。

範例2-使用 useContext 改寫

在父元件中我們會建立並 export 一個 Context(這裡命名為 MyContext),其他元件則直接引入使用,不再需要 props 傳遞。

Parent.js

import React, { useState, createContext } from 'react';
import Child from './Child';

// 在父元件中建立並 export Context
export const MyContext = createContext();

function Parent() {
const [user, setUser] = useState({ name: 'Alice' });

return (
<MyContext.Provider value={{ user, setUser }}>
<div>
<h1>父元件</h1>
<Child />
</div>
</MyContext.Provider>
);
}

export default Parent;

Child.js

import React from 'react';
import GrandChild from './GrandChild';

function Child() {
return (
<div>
<h2>子元件</h2>
{/* 直接呼叫 GrandChild,不需要傳遞 props */}
<GrandChild />
</div>
);
}

export default Child;

GrandChild.js

import React, { useContext } from 'react';
import { MyContext } from './Parent';

function GrandChild() {
// 直接使用 useContext 取得資料
const { user, setUser } = useContext(MyContext);

const changeUser = () => {
setUser({ name: 'Bob' });
};

return (
<div>
<h3>孫元件</h3>
<p>使用者名稱:{user.name}</p>
<button onClick={changeUser}>更改使用者</button>
</div>
);
}

export default GrandChild;
avatar-img
電資鼠 - 您的學習好夥伴
8會員
200內容數
在當今數位時代,電資領域人才需求爆發式成長,不論是前端網頁設計、嵌入式開發、人工智慧、物聯網還是軟硬體整合,這些技術都在改變世界。而掌握 C/C++、Python、數位邏輯、電路學與嵌入式開發等大學電資領域的課程,正是進入這個高薪、高需求產業的關鍵!
留言
avatar-img
留言分享你的想法!
在 React 中,狀態管理是構建複雜應用的重要一環,其中 useContext 與 Redux 都提供了解決方案,但它們各有優缺點和適用場景。 有鑑於Redux以英文教學為主,網上中文的教學不多,初學者會遇到一些困難,所以本章節希望以一篇文章帶領你快速入門Redux,透過實作的方式上手這個技能!
在本章,我們將使用 React Hooks(useState、useEffect、useRef)來 開發一個碼錶 (Stopwatch) 應用。
透過本章學習,你將掌握 useRef() 的核心概念與最佳應用方式,提高 React 應用的效能與靈活性!
在 React 中,狀態管理是構建複雜應用的重要一環,其中 useContext 與 Redux 都提供了解決方案,但它們各有優缺點和適用場景。 有鑑於Redux以英文教學為主,網上中文的教學不多,初學者會遇到一些困難,所以本章節希望以一篇文章帶領你快速入門Redux,透過實作的方式上手這個技能!
在本章,我們將使用 React Hooks(useState、useEffect、useRef)來 開發一個碼錶 (Stopwatch) 應用。
透過本章學習,你將掌握 useRef() 的核心概念與最佳應用方式,提高 React 應用的效能與靈活性!