How to Convert an SVG into a React Component: A Simple Guide

Posted on: Apr 22, 2025

11 mins read

How to Convert an SVG into a React Component: A Simple Guide

Last week, as I was working on a project, I found myself working on a design that was using an icon library I wasn't able to import. I contemplated using Lucide icons for the icons that matched and finding alternatives to the ones I couldn't find. But later, I decided to export the icons instead.

The challenge was that I needed a way to dynamically change the style of the icon in various states. Then I remembered a previous project where I turned SVGs into React components. This post will show you how easy it is to do.

TL;DR

  • Convert your SVG code into a React component by wrapping it in a function
  • Use className prop to enable dynamic styling
  • Replace hardcoded colours with currentColor or custom color props to allow colour inheritance
  • Spread additional props to the SVG element for maximum flexibility
  • Use the component like any other React component with dynamic classes

Prerequisites

Before we dive in, you should have:

  • Basic knowledge of React components
  • Understanding of SVG structure
  • A React project set up
  • An SVG you want to convert

Understanding SVGs in React

SVGs (Scalable Vector Graphics) are perfect for icons and illustrations in React applications because they scale perfectly without losing quality. When working with SVGs in React, you have several options:

  1. Import them as image files with <img src="icon.svg" />
  2. Use an icon library
  3. Convert them into React components

There are multiple ways to use SVGs in React, but the most flexible and powerful method is to convert them into React components. This allows you to take full advantage of React's capabilities, such as props, state, and lifecycle methods.

Converting SVGs to React components offers significant advantages:

  • You can dynamically change properties like size and colour
  • You can add interactions and animations
  • Components are reusable across your project
  • You maintain better control over the SVG rendering

Converting an SVG into a React Component

In this section, we'll walk through the process of converting an SVG into a React component.

Step 1: Obtain the SVG Code

First, you need the raw SVG code. You can get this from design tools like Figma, Sketch, or Illustrator, or download icons from icon libraries like Lucide.

For this example, let's say you have a simple hamburger menu icon:

jsx
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="black"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-menu-icon lucide-menu">
<line x1="4" x2="20" y1="12" y2="12" />
<line x1="4" x2="20" y1="6" y2="6" />
<line x1="4" x2="20" y1="18" y2="18" />
</svg>

Step 2: Create a React Component Structure

Next, create a new React component that will return the SVG:

jsx
export const MenuIcon = () => (
// SVG code will go here
);

Step 3: Insert the SVG Code Inside the Component

Place your SVG code inside the component.

jsx
export const MenuIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="black"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round">
<line x1="4" x2="20" y1="12" y2="12" />
<line x1="4" x2="20" y1="6" y2="6" />
<line x1="4" x2="20" y1="18" y2="18" />
</svg>
);

Step 4: Make the SVG Dynamically Stylable with Props

To make our SVG component flexible, we'll accept props, particularly className for styling:

jsx
export const MenuIcon = ({ className, ...props }) => (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="black"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
{...props}>
<line x1="4" x2="20" y1="12" y2="12" />
<line x1="4" x2="20" y1="6" y2="6" />
<line x1="4" x2="20" y1="18" y2="18" />
</svg>
);

Here, we're:

  1. Destructuring className from props
  2. Using the spread operator {...props} to pass any additional props to the SVG
  3. Adding the className to the SVG element

Step 5: Use currentColor for Dynamic Colour Changes

For maximum flexibility, replace hardcoded colour values with currentColor:

jsx
export const MenuIcon = ({ className, ...props }) => (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor" // Changed from "black" to "currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
{...props}>
<line x1="4" x2="20" y1="12" y2="12" />
<line x1="4" x2="20" y1="6" y2="6" />
<line x1="4" x2="20" y1="18" y2="18" />
</svg>
);

Using currentColor allows the SVG to inherit the text colour from its parent element through CSS, making it incredibly versatile.

How to Use the SVG Component

Now that we've created our SVG component, we can use it like any other React component:

jsx
export default function IconDemo() {
return (
<div className="flex items-center gap-4">
{/* Basic usage */}
<MenuIcon />
{/* With hover effect */}
<MenuIcon className="transition hover:text-blue-500" />
{/* Different size and colour */}
<MenuIcon className="h-14 w-14 text-green-600" />
</div>
);
}

In this example, we're using Tailwind CSS classes to style the SVG. You can easily change the size, colour, and hover effects by modifying the className prop.

A demonstration of converted SVGs used as React components

Figure 1: Example of SVGs converted into React components with dynamic styling.

Advanced Techniques

Handling Multiple Colours

SVGs often contain multiple elements with different colours. Here are progressive approaches to handle these cases:

1. Basic Approach: Using Individual Colour Props

For SVGs with just a few different coloured elements:

jsx
export const MultiColourIcon = ({
className,
primaryColour,
secondaryColour,
...props
}) => (
<svg
className={className}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}>
<line
x1="4"
x2="20"
y1="12"
y2="12"
stroke={primaryColour || "currentColor"}
/>
<line
x1="4"
x2="20"
y1="6"
y2="6"
stroke={secondaryColour || "currentColor"}
/>
<line x1="4" x2="20" y1="18" y2="18" stroke="currentColor" />
</svg>
);
// Usage with multiple colours
export default function IconDemo() {
return (
<div className="flex items-center gap-4">
<MultiColourIcon
primaryColour="red"
secondaryColour="blue"
className="h-10 w-10"
/>
</div>
);
}

In this example, we added primaryColour and secondaryColour props to allow customisation of specific elements. This is useful for SVGs with only a few colourable parts.

An SVG icon with multiple colours applied dynamically

Figure 2: Multi-coloured SVG icon using props for primary and secondary colours.

2. Advanced Approach: Using a Colours Object

For complex SVGs with many coloured elements, a more scalable approach uses a colours object:

jsx
export const ComplexIcon = ({ className, colours = {}, ...props }) => {
// Default colours that will be used if not overridden
const defaultColours = {
primary: "currentColor",
secondary: "currentColor",
accent: "#FF5733",
background: "transparent",
outline: "#333333",
// Add more as needed
};
// Merge default colours with provided colours
const mergedColours = { ...defaultColours, ...colours };
return (
<svg
className={className}
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}>
{/* Background rectangle */}
<rect
x="0"
y="0"
width="24"
height="24"
fill={mergedColours.background}
/>
{/* Primary elements */}
<path
d="M5 3h14v2H5V3z"
fill={mergedColours.primary}
stroke={mergedColours.outline}
/>
{/* Secondary elements */}
<path d="M3 21h18v-2H3v2z" fill={mergedColours.secondary} />
{/* Accent elements */}
<path d="M5 16h14v-2H5v2z" fill={mergedColours.accent} />
</svg>
);
};
// Usage examples
export default function ComplexIconDemo() {
return (
<div className="flex gap-4">
{/* Using default colours with class-based text colour */}
<ComplexIcon className="h-8 w-8 text-blue-500" />
{/* Customising specific colours */}
<ComplexIcon
className="h-8 w-8"
colours={{
primary: "#FF0000", // Red
secondary: "#00FF00", // Green
accent: "#0000FF", // Blue
}}
/>
{/* Complete colour scheme override */}
<ComplexIcon
className="h-8 w-8"
colours={{
primary: "#E91E63", // Pink
secondary: "#9C27B0", // Purple
accent: "#673AB7", // Deep Purple
background: "#F5F5F5", // Light grey background
outline: "#212121", // Dark outline
}}
/>
</div>
);
}

This approach provides several advantages:

  • Default colours can be established but easily overridden
  • Colour schemes can be defined once and reused across multiple icons
  • The component remains clean even with many colourable elements
  • You can set theme-specific colour schemes throughout your application

A complex SVG icon with a fully customized colour scheme

Figure 3: Complex SVG icon with a custom colour scheme applied using a colours object.

Animating SVG Components

You can animate SVG components using CSS transitions or React animation libraries:

jsx
export const LoaderIcon = ({ className, ...props }) => (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
{...props}>
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
</svg>
);
// Usage with animation
export default function LoaderDemo() {
return (
<div className="flex h-screen items-center justify-center">
<LoaderIcon className="animate-spin text-blue-500" />
</div>
);
}

In this example, we use the animate-spin class from Tailwind CSS to create a spinning loader icon. You can also use CSS keyframes or libraries like Framer Motion for more complex animations.

Figure 4: Animated SVG loader icon demonstrating the use of CSS animations.

Using SVG Components in Next.js

The approach works perfectly in Next.js applications as well. For optimal usage in Next.js, you might want to place your SVG components in a dedicated directory like components/icons/.

Common Issues and Troubleshooting

React SVG Icon Not Showing/Rendering

If your SVG component isn't rendering at all, there are several common causes to check:

  1. JSX attribute naming: SVG attributes in React need to use camelCase instead of kebab-case. For example:
jsx
// Incorrect (kebab-case)
<svg stroke-width="2" stroke-linecap="round">
// Correct (camelCase)
<svg strokeWidth="2" strokeLinecap="round">
  1. Missing closing tags: Make sure all SVG elements have closing tags or are self-closing:
jsx
// Incorrect
<path d="M5 3h14v2H5V3z">
// Correct
<path d="M5 3h14v2H5V3z" />
  1. SVG namespace issues: Ensure the SVG has the correct namespace:
jsx
<svg xmlns="http://www.w3.org/2000/svg" ... >
  1. Invalid viewBox: Check that the viewBox attribute has valid values (four numbers separated by spaces):
jsx
// Correct
viewBox = "0 0 24 24";
  1. CSS override: Check if any CSS is setting display: none or visibility: hidden on your SVG.

  2. Incorrect path data: Verify that path data strings are properly formatted with no syntax errors.

jsx
// Example of properly formatted path data
<path d="M5 3h14v2H5V3z" />
  1. Missing return statement: Ensure you're actually returning the SVG from your component:
jsx
// Incorrect (no return)
export const MenuIcon = ({ className, ...props }) => {
<svg className={className} viewBox="0 0 24 24" {...props}>
<path d="M5 3h14v2H5V3z" />
</svg>;
};
// Correct (with return)
export const MenuIcon = ({ className, ...props }) => {
return (
<svg className={className} viewBox="0 0 24 24" {...props}>
<path d="M5 3h14v2H5V3z" />
</svg>
);
};
// Also correct (implicit return with parentheses)
export const MenuIcon = ({ className, ...props }) => (
<svg className={className} viewBox="0 0 24 24" {...props}>
<path d="M5 3h14v2H5V3z" />
</svg>
);
  1. Incorrect import/export: Ensure you're importing and exporting the component correctly in your files.
jsx
// Importing
import { MenuIcon } from "./MenuIcon";
// Exporting
export { MenuIcon };

SVG Not Scaling Properly

If your SVG doesn't scale correctly with the classes you provide, check if the width and height attributes are overriding your CSS. You can remove these attributes and rely solely on the viewBox:

jsx
// Before
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
{...props}>
{/* paths */}
</svg>
// After
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
{...props}>
{/* paths */}
</svg>

Alternative Methods

While manual conversion is straightforward for simple SVGs, there are tools that can help automate the process, especially for complex icons or when dealing with many SVGs:

  1. SvgViewer - A tool to convert SVGs to different formats: SVG Viewer
  2. SVGR - Another tool that converts SVGs into React components: SVGR Playground

These tools are especially helpful when working with complex SVGs or when you need to convert a large number of icons at once.

Frequently Asked Questions

1. How do I animate SVG components in React?

You can animate SVG components using CSS animations, transitions, or libraries like Framer Motion. For simple animations, Tailwind CSS classes like animate-spin or animate-pulse work well.

2. Can I convert multiple SVGs at once?

Yes, tools like SVGR allow batch conversion of SVG files to React components. This is particularly useful when working with icon sets.

3. How do I handle SVGs with multiple colours?

For SVGs with multiple colours, you can either:

  1. Replace all colours with currentColor if you want them to change together
  2. Add specific props for each colour you want to control separately
  3. Use a colours object to manage multiple colour elements systematically

4. Is there any performance impact?

Using SVGs as React components is generally performance-friendly. However, very complex SVGs with many paths might impact performance. In such cases, consider optimising your SVGs using tools like SVGO.

Useful Resources

Connect with Me

Did you find this article helpful? I'd love to see how you've implemented SVG components in your projects!

🔗 Connect with me on LinkedIn or follow me on X(formerly Twitter) for daily tips and updates

✉️ Subscribe to my Newsletter for weekly dev insights

👩‍💻 Check out my open source projects on GitHub

Buy Me a Coffee if this article saved you time

❤️ Become a GitHub Sponsor to support my open source work

🤝 Visit my Sponsorship page or Affiliate Links page for more ways to support me

Happy coding! 🚀

Simplify your workflow with free, ready-to-use Notion templates!

Subscribe to my newsletter 💌

Stay in the loop on the latest articles, tutorials, projects, and exclusive content focused on web development! 💻📚✨