React Context是什麼?
什麼是 React Context?
React Context 提供了一個方法,讓你可以在元件樹中「廣播」資料,讓任何位於該 Context 範圍內的元件都能存取這些資料,而不需要明確地透過 props 一層層傳遞。它的核心組成包括:
-
Context 物件:使用 React.createContext() 創建,定義了一個資料的「容器」。
-
Provider:Context 物件的提供者,負責將資料傳遞給元件樹中的子元件。
-
Consumer 或 useContext Hook:用來在元件中存取 Context 提供的資料。
什麼時候使用 React Context?
你應該在以下情況考慮使用 React Context:
-
當多個元件需要存取相同的資料(例如使用者登入狀態、主題設定)。
-
當你不想透過 props 一層層傳遞資料,特別是當元件樹很深時。
-
當你需要一個簡單的全域狀態管理方案,且不需要引入像 Redux 這樣的大型狀態管理庫。
不建議的情況:
-
如果只需要在相鄰的父子元件之間傳遞資料,直接用 props 會更簡單。
-
如果應用程式規模非常大且狀態管理很複雜,可能需要考慮 Redux 或 Zustand 等狀態管理庫。
如何使用 React Context?
以下是一個完整的教學範例,展示如何使用 React Context 來共享使用者資訊。我們會逐步說明,並提供完整的 JavaScript 程式碼,讓你可以直接操作。
步驟 1:創建 Context
首先,使用 React.createContext() 創建一個 Context 物件。
// context/UserContext.js
import { createContext } from "react";
// 創建一個 Context 物件,初始值可以設為 null 或預設值
const UserContext = createContext(null);
export default UserContext;
-
createContext:創建一個 Context 物件,這個物件包含 Provider 和 Consumer。
-
初始值(這裡是 null)只有在元件沒有被任何 Provider 包圍時才會被使用。
步驟 2:提供 Context(使用 Provider)
接下來,在應用程式的頂層元件中使用 Provider 來提供資料。Provider 的 value 屬性會決定哪些資料可以被子元件存取。
// App.js
import React, { useState } from "react";
import UserContext from "./context/UserContext";
import UserProfile from "./components/UserProfile";
function App() {
// 假設這是使用者的狀態
const [user, setUser] = useState({
name: "小明",
email: "xiaoming@example.com",
});
return (
// 使用 Provider 包圍子元件,並傳遞 value
<UserContext.Provider value={{ user, setUser }}>
<div>
<h1>React Context 範例</h1>
<UserProfile />
</div>
</UserContext.Provider>
);
}
export default App;
-
UserContext.Provider:將 user 和 setUser 傳遞給所有子元件。
-
value 屬性可以傳遞任何資料,這裡我們傳遞了一個物件,包含 user 狀態和更新狀態的 setUser 函數。
步驟 3:在子元件中使用 Context(使用 useContext Hook)
在子元件中,使用 useContext Hook 來存取 Context 提供的資料。
// components/UserProfile.js
import React, { useContext } from "react";
import UserContext from "../context/UserContext";
function UserProfile() {
// 使用 useContext 來取得 Context 的 value
const { user, setUser } = useContext(UserContext);
// 函數:更新使用者名稱
const handleNameChange = () => {
setUser({ ...user, name: "小華" });
};
return (
<div>
<h2>使用者資料</h2>
<p>姓名:{user.name}</p>
<p>電子郵件:{user.email}</p>
<button onClick={handleNameChange}>將姓名改為小華</button>
</div>
);
}
export default UserProfile;
-
useContext(UserContext):從 Context 中提取 user 和 setUser。
-
這裡我們展示了如何讀取資料(user.name 和 user.email)以及如何更新資料(透過 setUser)。
步驟 4:執行與測試
-
確保你的專案結構如下:
src / context / UserContext.js;
components / UserProfile.js;
App.js; -
啟動你的 React 應用程式(假設你已用 create-react-app 建立專案):
npm start
-
開啟瀏覽器,你會看到:
-
使用者的姓名和電子郵件顯示在頁面上。
-
點擊「將姓名改為小華」按鈕,會更新姓名為「小華」,顯示 Context 的狀態更新功能正常。
-
完整的程式碼總覽
為了讓你更容易複製並操作,這裡將所有程式碼整理在一起:
// context/UserContext.js
import { createContext } from "react";
const UserContext = createContext(null);
export default UserContext;
// components/UserProfile.js
import React, { useContext } from "react";
import UserContext from "../context/UserContext";
function UserProfile() {
const { user, setUser } = useContext(UserContext);
const handleNameChange = () => {
setUser({ ...user, name: "小華" });
};
return (
<div>
<h2>使用者資料</h2>
<p>姓名:{user.name}</p>
<p>電子郵件:{user.email}</p>
<button onClick={handleNameChange}>將姓名改為小華</button>
</div>
);
}
export default UserProfile;
// App.js
import React, { useState } from "react";
import UserContext from "./context/UserContext";
import UserProfile from "./components/UserProfile";
function App() {
const [user, setUser] = useState({
name: "小明",
email: "xiaoming@example.com",
});
return (
<UserContext.Provider value={{ user, setUser }}>
<div>
<h1>React Context 範例</h1>
<UserProfile />
</div>
</UserContext.Provider>
);
}
export default App;
常見問題與注意事項
-
什麼時候不用 Context?
-
如果你的資料只需要在父子元件之間傳遞,直接用 props 更簡單。
-
如果你的應用程式規模很大,Context 的狀態更新可能會導致不必要的重新渲染,這時可以考慮其他狀態管理方案。
-
-
如何避免 Context 過度使用?
-
只把真正需要全域共享的資料放入 Context,例如主題、使用者資訊。
-
不要把所有狀態都丟進 Context,這樣會讓程式碼難以維護。
-
-
如何在多個 Context 中使用? 如果你有多個 Context,可以巢狀使用多個 Provider。例如:
<ThemeContext.Provider value={theme}>
<UserContext.Provider value={user}>
<App />
</UserContext.Provider>
</ThemeContext.Provider> -
使用 Consumer 代替 useContext 如果你不使用 Hook,可以用 Consumer 來存取 Context,但 useContext 更簡潔:
<UserContext.Consumer>
{({ user, setUser }) => (
<div>
<p>姓名:{user.name}</p>
</div>
)}
</UserContext.Consumer>
總結
React Context 是一個強大且簡單的工具,用來解決 props drilling 的問題,讓你可以在元件樹中共享資料。透過 createContext、Provider 和 useContext,你可以輕鬆地管理全域狀態。