隨著專案的成長,需要將父組件的資料傳遞給深層的子組件。這樣的資料傳遞過程會逐漸變得複雜且繁瑣。React 提供的 useContext
Hook 能夠有效解決這資料傳遞的問題,幫助我們在組件樹中更簡單地共享資料,而無需進行繁瑣的屬性傳遞(props drilling)。
當我們需要將父組件的資料一層層傳遞給子組件時,如果每層組件本身並不使用該資料,這種單純為了傳遞資料的過程被稱為 props drilling。這會讓程式碼變得冗長且難以維護。
import { useState } from "react";
function Component1() {
const [user, setUser] = useState("Jesse Hall");
return (
<>
<h1>{`Hello ${user}!`}</h1>
<Component2 user={user} />
</>
);
}
function Component2({ user }) {
return (
<>
<h1>Component 2</h1>
<Component3 user={user} />
</>
);
}
function Component3({ user }) {
return (
<>
<h1>Component 3</h1>
<Component4 user={user} />
</>
);
}
function Component4({ user }) {
return (
<>
<h1>Component 4</h1>
<Component5 user={user} />
</>
);
}
function Component5({ user }) {
return (
<>
<h1>Component 5</h1>
<h2>{`Hello ${user} again!`}</h2>
</>
);
}
export default Component1;
在上面的範例中,Component1
中的 user
狀態被傳遞到最內層的 Component5
。為了達成這個目的,我們需要將 user
屬性一層層傳遞下去,雖然 Component2
, Component3
, 和 Component4
並不需要使用這個資料。這就是典型的 props drilling 問題。
React 的 useContext
Hook 讓我們可以輕鬆地在組件間共享資料,而不需要經過層層的 props
傳遞。通過使用 useContext
,我們可以讓需要資料的組件直接訪問到最近的 Context Provider
提供的資料,避免了不必要的傳遞過程。
React.createContext()
創建一個 Context 對象。Context.Provider
將資料提供給組件樹中的其他組件。useContext
Hook 來取得 Context 中的資料。讓我們將上面的範例改寫,使用 useContext
來消除 props drilling:
import React, { useState, useContext } from "react";
// 1. 創建 UserContext
const UserContext = React.createContext();
function Component1() {
const [user, setUser] = useState("Jesse Hall");
return (
// 2. 使用 Provider 提供 user 資料給子組件
<UserContext.Provider value={user}>
<h1>{`Hello ${user}!`}</h1>
<Component2 />
</UserContext.Provider>
);
}
function Component2() {
return (
<>
<h1>Component 2</h1>
<Component3 />
</>
);
}
function Component3() {
return (
<>
<h1>Component 3</h1>
<Component4 />
</>
);
}
function Component4() {
return (
<>
<h1>Component 4</h1>
<Component5 />
</>
);
}
function Component5() {
// 3. 使用 useContext 來取得 user 資料
const user = useContext(UserContext);
return (
<>
<h1>Component 5</h1>
<h2>{`Hello ${user} again!`}</h2>
</>
);
}
export default Component1;
在這個範例中,我們用 UserContext
替代了原本的 props
傳遞,讓 Component5
能夠直接從 Context 中獲取 user
資料,而無需經過每一層組件。這樣一來,不僅解決了 props drilling 的問題,也讓程式碼更加清晰易懂。
useContext
特別適合在下列情境中使用:
useContext
可以有效簡化這個過程。雖然 useContext
提供了一種簡單的方式來共享資料,但在某些情況下,當 context 的資料頻繁更新時,可能會導致不必要的重渲染。如果應用中有頻繁變動的狀態,考慮使用其他狀態管理工具(如Redux) 可能會更合適。
本文將會同步更新到我的部落格