react-svg-loader: Failed to execute 'createElement' on 'Document': The tag name provided is not a valid name

I’m trying to have react-svg-loader 2.1.0 to load SVG using webpack, but I’m getting this error:

Failed to execute 'createElement' on 'Document': The tag name provided ('/packs/bundles/Project/components/LogoPage/images/name-f15c8edd029d0f795dd71e3e39079866.svg') is not a valid name I configured everything vanilla from the docs:

//webpack config: 
module: {
    loaders: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: "babel-loader"
          },
          {
            loader: "react-svg-loader",
            options: {
              jsx: true // true outputs JSX tags
            }
          }
        ]
      }
    ]
  }

the import statement in my react component:

import Logo from "./images/name.svg"; Not sure what other info might be relevant.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 26
  • Comments: 35

Most upvoted comments

I solved this issue using a Babel Plugin: https://www.npmjs.com/package/babel-plugin-inline-react-svg

Installation: yarn add babel-plugin-inline-react-svg --dev

Component import React from 'react'; import CloseSVG from './close.svg'; const MyComponent = () => <CloseSvg />;

Babel { "plugins": [ "inline-react-svg" ] }

import {ReactComponent as ArrowDownIcon} from '../assets/arrow-down.svg';

Importing like this worked for me.

The SVG is imported as a real react component, so can be used like this:

<ArrowDownIcon/>

Extra params are automatically accepted:

<ArrowDownIcon className="full-width" height={123}/>

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I ran into this again after the upgrade to 6.0. In the source it appears they’re including the svg extension in their file-loader path.

https://github.com/storybookjs/storybook/blob/7dc59dabc4621a587bed94e1ae780ae157d2246c/lib/core/src/server/preview/base-webpack.config.js#L69

I was able to fix it like this:

// main.js

module.exports = {
  webpackFinal: async (config) => {

    // Replaces the webpack rule that loads SVGs as static files to leave out SVG files for us to handle
    const indexOfRuleToRemove = config.module.rules.findIndex(rule => rule.test.toString().includes('svg'))
    config.module.rules.splice(indexOfRuleToRemove, 1, {
      test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
      loader: require.resolve('file-loader'),
      options: {
        name: 'static/media/[name].[hash:8].[ext]',
        esModule: false
      }
    })

    config.module.rules.push(
      {
        test: /.svg$/,
        use: ['@svgr/webpack'],
      },

    )
    return config
  },
}

FWIW I temporarily worked around it by including the source of my svg file inside a proper react component, it’s been a bit tricky because I had to change quite some attributes, for example: font-size had to become fontSize and all the dash ones similarly.

here’s my workaround code:

import React from "react";

const Logo = props =>
  <svg > 
.... svg code
  </svg>;

export default Logo;

The issue for me was that an svg file was being used as a component, when it was imported as a string.

Before:

import SVGIcon from '../../../assets/images/icon.svg';

const MyComponent = () => {
  return (
    <SVGIcon />
  )
}

After:

import SVGIcon from '../../../assets/images/icon.svg';

const MyComponent = () => {
  return (
    <img src={SVGIcon} alt="icon" />
  )
}

Hopefully this helps anyone else who comes across this thread!

thanks for the suggestion but svgr has the same issue as react-svg-loader with the setup I mentioned above

I hope it might help

But from your description your imported variable must be a string (since React is comparing with a tag name) Also I have got the very same issue when I tried to configure 2 different loaders (for inline svg and url svg) with a collision in the tests :

     ....
      {
        test: /\.(ttf|eot|svg)$/,
        use: 'file-loader?name=[name].[ext]',
      },
      {
        test: /\.inline.svg$/,
        use: 'svgr/webpack',
      },
     .....

I solved It with a simple exclusion

     ....
      {
        test: /\.(ttf|eot|svg)$/,
        use: 'file-loader?name=[name].[ext]',
        exclude: /\.inline.svg$/,
      },
      {
        test: /\.inline.svg$/,
        use: 'svgr/webpack',
      },
     .....

Hi I have the same issue and I fixed it changing my SVG file name From Checkmark.svg to checkmark.inline.svg don’t know why but it works

I had this same issue with an ejected create react app. The loader was only being run during in a dev environment and not the production. I had to add the below code right above file-loader in webpack.config.prod.js and it fixed my errors.

Webpack In webpack.config.prod.js

{
  test: /\.svg$/,
  use: [
    {
      loader: "babel-loader"
    },
    {
      loader: "react-svg-loader",
      options: {
        jsx: true // true outputs JSX tags
      }
    }
  ]
}

Component

import React from 'react';
import TwitterSVG from './twitter.svg';
const MyComponent = () => <TwitterSVG />;

@ArturBaybulatov’s solution did the trick.

Note that you have to use the import name ReactComponent exactly.

The ReactComponent import name is significant and tells Create React App that you want a React component that renders an SVG, rather than its filename.

See https://create-react-app.dev/docs/adding-images-fonts-and-files/#adding-svgs

Make sure you don’t have any other loader plugins trying to load/parse svg files like file-loader or url-loader.

Same issue, tried to add the webpack configuration and babel, still didnt work

@AfroDevGirl thank you so much it helped me a lot. I was using tsup (esbuild) to build React appliaction.

@colincmcc working like a charm, thank you.