Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting undefined when importing svg as ReactComponent in create-react-app project

Tags:

I'm getting following error when trying to load svg as ReactComponent.

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.

Check the render method of Icon.

I'm using create-react-app with typescript option to create project. If I'm understanding the document correctly, I should be able to import svgs as ReactComponent out of the box(since CRA2.0). But weirdly, I'm getting undefined for the imported component.

Adding Images, Fonts, and Files · Create React App https://facebook.github.io/create-react-app/docs/adding-images-fonts-and-files#adding-svgs

Currently using following packages.

    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-redux": "^6.0.1",
    "react-router-dom": "^5.0.1",
    "react-scripts": "^3.0.1",
    "@types/node": "^12.0.0",
    "@types/react": "^16.8.17",
    "@types/react-dom": "^16.8.4",
    "@types/react-redux": "^7.0.8",
    "@types/react-router-dom": "^4.3.3",

My code is below.

Icon.tsx

import * as React from 'react';
import { ReactComponent as IconSvg } from './IconSvg.svg';

const Icon: React.FC<IconProps> = props => {
  console.log(IconSvg); // undefined
  return (<IconSvg />);
};

export default Icon;

custom.d.ts

declare module '*.svg' {
  import React = require('react');
  export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
  const src: string;
  export default src;
} 

tsconfig.json

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "baseUrl": "src",
    "rootDir": "src",
    "outDir": "build/dist",
    "target": "es5",
    "jsx": "react",
    "lib": [
      "es6",
      "dom"
    ],
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": false,
    "allowSyntheticDefaultImports": true
  },
  "include": [
    "src",
    "custom.d.ts"
  ],
  "exclude": [
    "node_modules",
    "node_scripts",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

Any advice is appreciated.

like image 507
ysjn Avatar asked Jun 19 '19 17:06

ysjn


1 Answers

TLDR: import MySvg from "MySvg.svg" then <img src={MySvg}/>

To import an SVG: import MySvg from "MySvg.svg" which will save the path as a string inside MySvg.

To render it, use an img tag as in standard HTML, since MySvg is actually a path: <img src={MySvg}/>

The reason you get undefined is that you are destructuring a string.

like image 101
Gabriel Petersson Avatar answered Oct 13 '22 06:10

Gabriel Petersson