最初我以為共用元件的設計應該沒哪麼難,不就像設計 function 時,會重複用到的就把它拆出來就好了,元件也是一樣的道理吧,但隨著情境越來越多樣,要適用的情境越來越複雜,才發現原來我完全不懂「抽象化」,真正設計出能夠多次重用的元件,實際上比我想像的要難得多。
在製作共用元件上時的困擾包括:
這幾天的文章將探討如何解決設計共用元件時遇到的這些問題。首先,我們來定義一下什麼是「好」的共用元件。
共用元件是指那些能夠在多個地方被重複使用的元件,以下是我整理的「好」的共用元件該有的特性:
前面提到如果支援 A、支援 B、又支援 C,不會變得超級複雜嗎?如果有遇到這樣的困擾,代表在為了支援多個情境可能用大量的條件渲染邏輯寫在元件裡面,像是用 ? :
條件運算符或 if
else
來處理不同的情況,這樣做會讓元件變得非常複雜、不易維護,此時也表示元件設計得不夠抽象化。
// ❌ 錯誤範例:過度依賴條件渲染
const IdolCard = ({ role }) => {
return (
<div
className={
role === "Shiver"
? "bg-blue-500"
: role === "Frye"
? "bg-yellow-400"
: role === "Big Man"
? "bg-red-400"
: "bg-black"
}
>
<p>
{role === "Shiver"
? "莎莎"
: role === "Frye"
? "曼曼"
: role === "Big Man"
? "鬼福"
: ""}
</p>
</div>
);
};
const App = () => (
<div>
<IdolCard role="Shiver" />
<IdolCard role="Frye" />
<IdolCard role="Big Man" />
</div>
);
那其實最簡單的解決方式,就是昨天 Day 7 - 打造靈活的元件設計 —— 將樣式傳進元件 中提到的使用 樣式傳入元件 或 render props 的方式,來提高元件的抽象度~
// ⭕️ 正確範例:使用 Render Props
const IdolCard = ({ render }) => {
return render();
};
const App = () => {
return (
<div>
<IdolCard
render={() => (
<div className="bg-blue-500 p-4">
<p>莎莎</p>
</div>
)}
/>
<IdolCard
render={() => (
<div className="bg-yellow-400 p-4">
<p>曼曼</p>
</div>
)}
/>
<IdolCard
render={() => (
<div className="bg-red-400 p-4">
<p>鬼福</p>
</div>
)}
/>
</div>
);
};