Dynamic Icon Rendering
In content management systems (CMS) or admin settings portals, icon names are often stored as strings in a database (such as "home", "settings", or "user"). Let us explore how to render Lucide Icons dynamically based on these strings.
1. Static Component Mapping (Recommended for Small Sets)
If you only use a small number of icons, the simplest and most performant approach is to create a static mapping object:
import { Home, Settings, User } from "lucide-react";
// Static registry mapping string names to component definitions
const iconRegistry: Record<string, React.ComponentType<{ className?: string }>> = {
home: Home,
settings: Settings,
user: User,
};
interface DynamicIconProps {
name: string;
className?: string;
}
export function DynamicIcon({ name, className }: DynamicIconProps) {
const IconComponent = iconRegistry[name];
if (!IconComponent) {
return <span className="text-xs text-red-500">Icon not found</span>;
}
return <IconComponent className={className} />;
}This ensures tree-shaking works perfectly, keeping your production bundle small.
2. Dynamic Imports (For Large Icon Lists)
If you need to support the entire Lucide icon catalog without bloating your application bundle, use lazy loading via dynamic imports.
In Next.js, you can implement this using the built-in dynamicIconImports helper provided by lucide-react:
import dynamic from "next/dynamic";
import lucideDynamicImports from "lucide-react/dynamicIconImports";
interface LazyIconProps {
name: keyof typeof lucideDynamicImports;
className?: string;
}
export function LazyIcon({ name, className }: LazyIconProps) {
// Lazily load the specific icon file on-demand
const DynamicIconComponent = dynamic(lucideDynamicImports[name]);
return <DynamicIconComponent className={className} />;
}This loads only the specific icon code files required for the current view, keeping your initial page load times fast.