question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Dynamic import doesn't work with SVG imported as ReactComponents

See original GitHub issue

Is this a bug report?

Yes

Did you try recovering your dependencies?

Yes

Which terms did you search for in User Guide?

SVG, ReactComponent, dynamic import

Environment

  System:
    OS: macOS 10.14
    CPU: x64 Intel(R) Core(TM) i5-4278U CPU @ 2.60GHz
  Binaries:
    Node: 10.11.0 - /usr/local/bin/node
    Yarn: 1.7.0 - /usr/local/bin/yarn
    npm: 6.4.1 - /usr/local/bin/npm
  Browsers:
    Chrome: 69.0.3497.100
    Firefox: 61.0.2
    Safari: 12.0
  npmPackages:
    react: ^16.5.2 => 16.5.2
    react-dom: ^16.5.2 => 16.5.2
    react-scripts: 2.0.3 => 2.0.3
  npmGlobalPackages:
    create-react-app: 2.0.2

Steps to Reproduce

  1. Try to import SVG as ReactComponet using import(). Example code below

Expected Behavior

SVG loads

Actual Behavior

Got following error in browser

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

This happens because importing module doesn’t contain ReactComponent property. Here’s console.log output from demo

Module {default: "/static/media/logo.5d5d9eef.svg", __esModule: true, Symbol(Symbol.toStringTag): "Module"}

Reproducible Demo

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  constructor (props) {
    super(props)
    this.logoComponent = 'div'
  }

  componentDidMount () {
    import('./logo.svg').then((m) => {
      console.log(m)
      this.logoComponent = m.ReactComponent
      this.forceUpdate()
    })
  }

  render() {
    const Logo = this.logoComponent

    return (
      <div>
        <Logo />
      </div>
    )
  }
}

export default App;

Workaround

  1. Create file with following content
import { ReactComponent as Logo } from './logo.svg'
export default Logo
  1. Use dynamic import as usual for this file

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:37
  • Comments:25 (1 by maintainers)

github_iconTop GitHub Comments

24reactions
thabemmzcommented, Jul 29, 2020

This fix only works in the Webpack-world

This seems to be caused by the fact that the Webpack plugin that adds the ReactComponent to each SVG that is imported somehow does not trigger on dynamic imports.

In the webpack config of CRA, you can see the configuration for this:

[
  require.resolve('babel-plugin-named-asset-import'),
  {
    loaderMap: {
      svg: {
        ReactComponent:
          '@svgr/webpack?-svgo,+titleProp,+ref![path]',
      },
    },
  },
],

As you can see, the @svgr/webpack loader is used to generate the ReactComponent and this loader is prepended to the filepath you specified for the svg.

This means enforcing the same loader on your dynamic SVG import should fix your issues. The only difference is that the ReactComponent is now the default output.

import('!!@svgr/webpack?-svgo,+titleProp,+ref!./logo.svg').then((m) => {
      console.log(m)
      this.logoComponent = m.default
      this.forceUpdate()
    })
11reactions
gaussyleancommented, Jan 5, 2022

With the update to 5.0.0 to CRA, !!@svgr/webpack?-svgo,+titleProp,+ref![svg_file_path] is not part of the config anymore, and isn’t being resolved with the @svgr/webpack?-svgo,+titleProp,+ref!. I’m not seeing ReactComponent with default when importing dynamically like import(`${name}.svg). Are there any clues on how to go about doing this now?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can i import the SVG file as a react component with dynamic ...
The default import from the svg file (which is also the Url property) is the data-url for the image. You can use that...
Read more >
Using React.lazy() to dynamically import svg files as ... - Reddit
Hey guys, so I've been trying to find a better way for us to store, load and render SVG icons on our website.Currently...
Read more >
Dynamic SVG Imports in Create-React-App | by Ryan Hutzley
In this post, I will show you how to dynamically import your SVGs in CRA using a custom hook. First, we'll dive into...
Read more >
Code-Splitting - React
Bundling is the process of following imported files and merging them into a single file: ... React.lazy takes a function that must call...
Read more >
Features | Vite
Vite will detect such bare module imports in all served source files and perform the ... For example, to make the default import...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found