Search code examples
imagesvgcreate-react-appfilepath

Why is SVG imported as IMG in React not working?


I don't understand why this SVG is not displaying with create-react-app; in most cases it's producing errors which I don't understand. I think it's a problem with the file path but it looks correct to me! I've read all the resources I can find and tried everything but something is still wrong. Thank you in advance for your help.

The closest I can get to it working is like this:

<img src="../assets/images/logo-cool-earth-white.svg" alt="Cool Earth" />

The alt text is displayed in the browser with the tooltip inside the inspector: "File could not be found".

I have also tried this:

import CoolEarth from '../assets/images/logo-cool-earth-white.svg';
...
<img src={CoolEarth} alt="Cool Earth" />

and this:

import {ReactComponent as CoolEarth} from '../assets/images/logo-cool-earth-white.svg';
...
<CoolEarth />

(The img component is placed inside a function () { return (<><div></div></>) })

The error message I get for the last 2 attempts is:

Compiled with problems:

ERROR in ./src/assets/images/logo-cool-earth-white.svg

Module build failed (from ./node_modules/file-loader/dist/cjs.js):
Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:67:19)
    at Object.createHash (node:crypto:133:10)
    at getHashDigest (/Users/username/Documents/Clients/clientname/crypto-transfer/working crypto-transfer/node_modules/loader-utils/lib/getHashDigest.js:46:34)
    at /Users/username/Documents/Clients/clientname/crypto-transfer/working crypto-transfer/node_modules/loader-utils/lib/interpolateName.js:113:11
    at String.replace (<anonymous>)
    at interpolateName (/Users/username/Documents/Clients/clientname/crypto-transfer/working crypto-transfer/node_modules/loader-utils/lib/interpolateName.js:110:8)
    at Object.loader (/Users/username/Documents/Clients/clientname/crypto-transfer/working crypto-transfer/node_modules/file-loader/dist/index.js:29:48)

Here is the file structure:

src >
 components >
  Video.js
 assets >
  images >
   logo-cool-earth-white.svg
 App.js

Video.js (containing the SVG) is rendered inside App.js

SVG file looks like this:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 95 90" style="enable-background:new 0 0 95 90;" xml:space="preserve">
<path class="st0" d="...">
...
</svg>

Solution

  • (With the help from a friend) I was able to find a solution to this problem.

    Place the SVG into a react component like this:

    import React from 'react';
    
    function CoolEarth() {
      return (
       <svg>...</svg>
      );
    };
    
    export default CoolEarth;
    

    Place CoolEarth.js into a subfolder of the components folder and import it into Video.js like this:

    import CoolEarth from "./svg/CoolEarth";
    

    If anyone knows why this works over my other attempts, please do elaborate.