當一個父元件包含多個嵌套子元件,並且子元件需要最外層父元件的資料時,我們需要將資料從最頂層傳遞到最底層,讓子元件能夠訪問和使用這些資料,這就是 Prop Drilling,讓我們舉個例子:
// 最底層的 DComponent 元件需要最頂層 AComponent 元件的 name 屬性
// 此時我們需要將 name 逐層傳遞下去,這就是 Prop Drilling
function AComponent() {
const [name, setName] = useState("John");
return <BComponent name={name} />
}
function BComponent({ name }) {
return <CComponent name={name} />
}
function CComponent({ name }) {
return <DComponent name={name} />
}
function DComponent({ name }) {
return <h1>{name}</h1>;
}
要應對 Prop Drilling,有幾種方法可以考慮:
const NameContext = createContext();
// A 元件將狀態傳入
function AComponent() {
const [name, setName] = useState("John");
return (
<NameContext.Provider value={name}>
<BComponent />
</NameContext.Provider>
);
}
// 不需要傳遞 name 屬性
function BComponent() {
return <CComponent />
}
// 不需要傳遞 name 屬性
function CComponent() {
return <DComponent />
}
// 不需要通過 B 和 C 元件,D 元件直接使用
function DComponent() {
const name = useContext(NameContext);
return (
<div>
<p>Name: {name}</p>
</div>
);
}
// 透過 Children Prop 的方式,直接將最底層的 DComponent 寫在 AComponent 裡面,並直接傳遞 name 狀態進去
// 這種方法並不適用於所有情況
function AComponent() {
const [name, setName] = useState("John");
return (
<BComponent>
<CComponent>
<DComponent name={name} />
</CComponent>
</BComponent>
);
}
function BComponent({ children }) {
return <div>{children}</div>;
}
function CComponent({ children }) {
return <div>{children}</div>;
}
function DComponent({ name }) {
return <h1>{name}</h1>;
}
Prop Drilling 可能導致程式碼變得複雜且難以維護,因此當出現 Prop Drilling 的時候,可以嘗試使用文章提供的幾種方式來處理,以確保程式碼的簡潔和可維護性。