今天這篇文章將介紹如何在元件間傳遞樣式,也會介紹如何透過 React Design Pattern 中的 Render Props Pattern 來打造靈活、可重複使用的元件,那以下會使用 Tailwind 作為範例。
在開發中,我們常常需要讓元件在不同的情境下顯示不同的樣式。如果每次改變樣式就要重新設計一個新元件,不但會增加維護的難度,也可能導致程式碼的重複。
有寫過 React 的人應該都對 props
不陌生,除了可以在父元件與子元件中傳遞資料外, 還可以用來傳遞「樣式」喔,這樣我們能根據需求調整外觀,同時保持元件的邏輯不變。
透過 className
傳遞樣式
<Button>
接收 className
作為 props 傳入元件,來變換成不同顏色:
const Button = ({ className, children }) => {
return (
<button className={`px-4 py-2 font-semibold rounded ${className}`}>
{children}
</button>
);
};
// 藍色的按鈕
<Button className="bg-blue-500 hover:bg-blue-700 text-white">
Click
</Button>
// 紅色的按鈕
<Button className="bg-red-500 hover:bg-red-700 text-white">
Click
</Button>
Render Props Pattern 是一種 React 的設計模式,可以實現在多個元件之間共用邏輯和資料,透過 render prop 或是 children
prop 將資料傳遞給元件,從而改變其渲染方式。透過這種模式,每次都能傳入不同的資料來渲染不同的內容,使得元件可以更加靈活。
Render Props Pattern 用法:
render()
是一個能回傳 JSX 元素的函式,負責渲染元件的內容。render()
作為 prop
,除了 render prop 之外,元件本身不會渲染任何內容。(參考自 Render Props Pattern)<Button>
接收 render()
,來控制不同的按鈕的渲染:
const Button = ({ className, render, onClick }) => {
return (
<button
className={`px-4 py-2 font-semibold rounded ${className}`}
onClick={onClick}
>
{render()}
</button>
);
};
// 顯示 "提交" 的藍色按鈕
<Button
className="bg-blue-500 hover:bg-blue-700 text-white"
onClick={() => alert('按鈕點擊!')}
render={() => <span>提交</span>}
/>
// 顯示 "取消" 的紅色按鈕
<Button
className="bg-red-500 hover:bg-red-700 text-white"
onClick={() => alert('取消操作!')}
render={() => <span>取消</span>}
/>
其他:
雖然叫做 render props,但是不一定要命名成 render
。
props 除了可以傳遞資料、樣式外,由於 first-class function 的特性,所以也可以用來傳遞「函式」喔。Render Props Pattern 算是以此特性發展出來的 coding 技巧。
First-class function: 函式可以作為參數傳入其他函式、從函式返回,甚至可以被賦值給變數。
— MDN Web docs
本篇文章沒有細講 children
prop,從技術上來說,它也是一個 render prop,想了解更多可參考 Children as a function 的段落。