image of blg

The best way to manage icons in React/Nextjs

When constructing a UI, the significance of SVG cannot be overstated. As the code base expands, the utilization of SVG also grows. In this blog, we will explore the top three methods for rendering SVG and identify the most optimal solution among them.

The initial approach involves utilizing the image tag for SVG rendering

const ImageSvg = () => <img src="path_to_svg_url.svg" />
const ImageSvg = () => <img src="path_to_svg_url.svg" />

Pros

This method is recommended exclusively for handling large-sized SVG files.

Corns

There is a delay before it appears on the screen, and styling the SVG is not possible in this scenario.

Most common approach, we directly render the SVG as a JSX component.

  1. We'll craft an SVG component named PlusSVG.tsx, allowing us to conveniently utilize this component in various locations.

    const PlusSVG = () => (
    <svg viewBox="0 0 50 50">
    <path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"></path>
    </svg>
    );
    const PlusSVG = () => (
    <svg viewBox="0 0 50 50">
    <path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"></path>
    </svg>
    );
  2. We will render the previously created component in the relevant sections as needed.

    import PlusSVG from "@/svg/PlusSvg"

    const App = () => (
    <div>
    <PlusSVG />
    </div>
    );
    import PlusSVG from "@/svg/PlusSvg"

    const App = () => (
    <div>
    <PlusSVG />
    </div>
    );

Pros

Easy to implement, customizable styling, and no flickering issues.

Corns

If you use the same SVG in multiple places, it adds unnecessary weight to the DOM, leading to an increase in bundle size, especially when dealing with numerous SVGs in your project.

The ultimate and most effective method for SVG usage is through the use of sprites.

Rendering Sprite as a react component

  1. Creating a reusable "Icon" component for rendering SVG icons.

    import { SVGProps } from "react";

    type ISvgPropType = {
    iconName: string;
    } & SVGProps<SVGSVGElement>;

    const Icon = ({ iconName, ...props }: ISvgPropType) => (
    <svg {...props} >
    <use href={`#${name}`} />
    </svg>
    );

    export default Icon;
    import { SVGProps } from "react";

    type ISvgPropType = {
    iconName: string;
    } & SVGProps<SVGSVGElement>;

    const Icon = ({ iconName, ...props }: ISvgPropType) => (
    <svg {...props} >
    <use href={`#${name}`} />
    </svg>
    );

    export default Icon;
  2. Developing a "Sprite" component to handle all SVG icons.

    const SVGSprite = () => (
    <svg xmlns="http://www.w3.org/2000/svg">
    <defs>
    <symbol id="plus" viewBox="0 0 24 24">
    <path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"></path>
    </symbol>
    <symbol id="heart" viewBox="0 0 24 24">
    <path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"></path>
    </symbol>
    </defs>
    </svg>
    );
    const SVGSprite = () => (
    <svg xmlns="http://www.w3.org/2000/svg">
    <defs>
    <symbol id="plus" viewBox="0 0 24 24">
    <path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"></path>
    </symbol>
    <symbol id="heart" viewBox="0 0 24 24">
    <path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"></path>
    </symbol>
    </defs>
    </svg>
    );
  3. Render the SpriteSvg in the App component

    import SpriteSvg from "@/SpriteSvg";

    const App = () => (
    <div>
    // remaining code
    <SpriteSvg />
    </div>
    );
    import SpriteSvg from "@/SpriteSvg";

    const App = () => (
    <div>
    // remaining code
    <SpriteSvg />
    </div>
    );
  4. How to use it

    import Icon from "@/Icon";

    const App = () => (
    <div>
    <Icon name="plus" />
    </div>
    );
    import Icon from "@/Icon";

    const App = () => (
    <div>
    <Icon name="plus" />
    </div>
    );

How to handel large Sprites in large Projects

  1. Create an SVG file for sprites and place it within the public folder.

    <!-- sprites.svg -->
    <svg xmlns="http://www.w3.org/2000/svg">
    <defs>
    <symbol id="plus" viewBox="0 0 24 24">
    <path
    d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"
    ></path>
    </symbol>
    <symbol id="heart" viewBox="0 0 24 24">
    <path
    d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"
    ></path>
    </symbol>
    </defs>
    </svg>
    <!-- sprites.svg -->
    <svg xmlns="http://www.w3.org/2000/svg">
    <defs>
    <symbol id="plus" viewBox="0 0 24 24">
    <path
    d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"
    ></path>
    </symbol>
    <symbol id="heart" viewBox="0 0 24 24">
    <path
    d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 24 13 L 24 24 L 13 24 L 13 26 L 24 26 L 24 37 L 26 37 L 26 26 L 37 26 L 37 24 L 26 24 L 26 13 L 24 13 z"
    ></path>
    </symbol>
    </defs>
    </svg>
  2. Preload the mentioned sprite.svg file by adding the following line to your index.html.

    <head>
    // remaining code
    <link rel="preload" as="image/svg+xml" href="/sprite.svg" />
    </head>
    <head>
    // remaining code
    <link rel="preload" as="image/svg+xml" href="/sprite.svg" />
    </head>
  3. Utilize the previously constructed Icon.tsx component by passing the respective name to it.