我有一個需求,需要在菜單中渲染一個項目列表,每個項目都有自己的圖標。
起初,我在菜單中硬編碼組件,像這樣:
const menu = [
{
title: '首頁',
icon: <HomeIcon className="mr-3 ml-1 h-5 w-5" />
},
{
title: '通知',
icon: <BellIcon className="mr-3 ml-1 h-5 w-5" />
},
{
title: '個人資料',
icon: <UserIcon className="mr-3 ml-1 h-5 w-5" />
},
];
使用非常酷的 @heroicons/react
套件。
在 JSX 中,我使用 menu
陣列迭代顯示 {item.icon}
。
但是,後來我需要根據應用程序的響應狀態更改使用的 Tailwind 類,所以我使用了 react-responsive
套件。
我決定改為傳遞一個字符串,因此首先做了這個更改:
const menu = [
{ title: '首頁', icon: 'HomeIcon' },
{ title: '通知', icon: 'BellIcon' },
{ title: '個人資料', icon: 'UserIcon' },
];
const Icon = (props) => {
const { name } = props;
let icon = null;
if (name === 'HomeIcon') icon = HomeIcon;
if (name === 'BellIcon') icon = BellIcon;
if (name === 'UserIcon') icon = UserIcon;
return React.createElement(icon, { ...props });
};
...
<Icon name={item.icon} />
另一種解決方案是使用物件查找組件,而不是一堆 if
檢查:
const icons = {
HomeIcon,
BellIcon,
UserIcon,
};
const Icon = (props) => {
const { name } = props;
const TheIcon = icons[name];
return <TheIcon {...props} />;
};
<Icon name={item.icon} />
我必須使用
TheIcon
,因為 React 組件以大寫字母開頭是一種約定。
這樣已經足夠好了,但後來我意識到可以以更簡潔的方式來實現,直接在 menu
陣列中使用實際的組件而不是字符串:
const menu = [
{ title: '首頁', icon: HomeIcon },
{ title: '通知', icon: BellIcon },
{ title: '個人資料', icon: UserIcon },
];
const Icon = (props) => {
const { icon } = props;
const TheIcon = icon;
return <TheIcon {...props} />;
};
...
<Icon icon={item.icon} />