skip to Main Content

I downloaded the Vercel Ecommerce template and want to use it with custom icons.

I have installed @svgr/webpack and configured next.config.mjs:

export default {
  images: {
    formats: ['image/avif', 'image/webp'],
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'cdn.shopify.com',
        pathname: '/s/files/**'
      }
    ]
  },
  webpack(config) {
    config.module.rules.push({
      test: /.svg$/,
      oneOf: [
        {
          resourceQuery: /react/, // ?react query => @svgr/webpack
          use: ['@svgr/webpack']
        },
        {
          type: 'asset/resource' // Default asset voor andere SVG's
        }
      ]
    });

    return config;
  }
};

In app/assets/icons/briefcase.svg I will save multiple svg files. Then I made a reusible component:

import React from 'react';
// import BriefcaseIcon from 'assets/icons/briefcase.svg';
import BriefcaseIcon from '@/icons/briefcase.svg';

const icons = {
  briefcase: BriefcaseIcon
};

const Icon = ({ name, size = 24, color = 'currentColor', ...props }) => {
  console.log('NAAM: ', name);
  const SvgIcon = icons[name];
  if (!SvgIcon) {
    console.warn(`Icon '${name}' bestaat niet.`);
    return null;
  }
  return <SvgIcon width={size} height={size} fill={color} {...props} />;
};

export default Icon;

Now when I try to use the component, I get the following error message:

React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

If I console.log the icon, I get this object:

{
    "src": "/_next/static/media/briefcase.59a4a40f.svg",
    "width": 24,
    "height": 24,
    "blurDataURL": null,
    "blurWidth": 0,
    "blurHeight": 0
}

Any idea what might be wrong? Seems that the svg loader is not working properly.

2

Answers


  1. There is a pattern I usually use in every project to add and utilize SVG icons:

    Icons.tsx :

    export const Icons = {
    
      Star: (props: React.SVGProps<SVGSVGElement>) => (
        <svg
          {...props}
          fill="currentColor"
          viewBox="4 4 48 48"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="m19.2 36.4-4.75-10.45L4 21.2l10.45-4.75L19.2 6l4.75 10.45L34.4 21.2l-10.45 4.75ZM36.4 42l-2.35-5.25-5.25-2.35 5.25-2.4 2.35-5.2 2.4 5.2 5.2 2.4-5.2 2.35Z" />
        </svg>
      ),
    };
    

    and u can import and use it like this:

      import { Icons } from "./Icons";
      <Icons.Star className="size-5" />
    

    and I use https://svg2jsx.com to convert the normal svg to jsx one.

    Login or Signup to reply.
  2. Create react component for the svg import. i.e. for github:

    import React from 'react';
    
    interface Props {
        width: number;
        className?: string;
    }
    
    const GithubLogo = ({ width, className }: Props) => {
        return (
            <svg
                xmlns='http://www.w3.org/2000/svg'
                fill='currentColor'
                width={width}
                className={className}
                viewBox='0 0 256 250'
            >
                <path
                    d='M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z'
                    fill='currentColor'
                />
            </svg>
        );
    };
    
    export default GithubLogo;

    then, use this component else where like so:

    import GithubLogo from '@/components/assets/svg/social-media/github.logo';
    
    const Page = () => {
      return (
        <Label className='flex flex-row items-center space-x-2'>
            <GithubLogo size={24} />
            <p>Github</p>
        </Label>
      )
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search