Support name-based dynamic icon imports
👋
It could be interesting to introduce a new DynamicIcon that dynamically imports and renders icons based on its name.
const CategoryList: React.FC = () => {
const { data: categories } = api.categories.list.useQuery();
return (
<div>
{categories?.map((category) => <DynamicIcon name={category.icon} />)}
</div>
);
}
Use case
This is useful for scenarios where the icon name is not known ahead of time (i.e. comes from an external source — backend, api, etc.) and does not affect tree-shaking, unlike doing import * as ....
Examples
Implementation
I think Lucide's implementation works quite good. They export a big lookup table of all icons and their respective dynamic import, which will be called when rendering the component.
They also accept a fallback component for when the icon hasn't loaded yet or if the name is invalid. Out of experience, it works quite well.
const dynamicImportMap = {
"a-arrow-down": () => import('./icons/a-arrow-down.js'),
"a-arrow-up": () => import('./icons/a-arrow-up.js'),
// ...
}
You can do dynamic imports in TypeScript like so:
export type PhosphorIcon = keyof Omit<
typeof import("@phosphor-icons/react/dist/ssr"),
"SSRBase"
>;
function DynamicIcon({ icon }: { icon: PhosphorIcon }) {
const Icon = dynamic(
() => import("@phosphor-icons/react").then((mod) => mod[icon]),
{
ssr: false,
}
);
return <Icon size={20} weight="bold" />;
}
Can you share sample code for usage? @aidinio
I guess this is how:
<DynamicIcon icon="a-arrow-up" />
Can you share sample code for usage? @aidinio
I guess this is how:
An example usage would be:
<DynamicIcon icon="ArrowUp" />
If you have code completion, it should show you a list of available options given that the icon property is typed.
Thanks @aidinio