Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reference a local svg in React?

Tags:

reactjs

The following code compiles just fine but the icon doesn't show up:

enter image description here

Icon.jsx component:

import React from 'react';
import { css } from 'emotion';

import ArrowRight from "./arrow-right.svg";

export const iconTypes = {
    arrowRight: 'ARROW_RIGHT',
   // arrowLeft: 'ARROW_LEFT',
}

const iconSrc = {
    ARROW_RIGHT: ArrowRight,
   // ARROW_LEFT: ArrowLeft,
}


export default function Icon({ type }) {
    return (
        <div>
            <img src={iconSrc[type]}/>
        </div>
    )
};

In the browser the request looks like this:

 http://localhost:9001/%22data:image/svg+xml,%3Csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20width='512'%20height='512'%20viewBox='0%200%20512%20512'%3E%20%3Ctitle%3E%3C/title%3E%20%3Cg%20id='icomoon-ignore'%3E%20%3C/g%3E%20%3Cpath%20d='M310.627%20438.627l160-160c12.497-12.496%2012.497-32.758%200-45.255l-160-160c-12.497-12.496-32.758-12.496-45.255%200s-12.497%2032.758%200%2045.255l105.373%20105.373h-306.745c-17.673%200-32%2014.327-32%2032s14.327%2032%2032%2032h306.745l-105.373%20105.373c-6.248%206.248-9.372%2014.438-9.372%2022.627s3.124%2016.379%209.372%2022.627c12.497%2012.497%2032.758%2012.497%2045.255%200z'%3E%3C/path%3E%20%3C/svg%3E%22 

Icon.jsx story:

import { action } from "@storybook/addon-actions"; 
import Icon from "../components/Icon/Index"; 
import { iconTypes } from "../components/Icon/Index";


    storiesOf("Icon", module)
        .add("with text", () => (
            <Icon type={iconTypes.arrowRight}>
            </Icon>
        ));

When I fill the src with a http path (for ex: "https://s.cdpn.io/3/kiwi.svg") it works just fine.

When I open the svg file directly in the browser it also opens fine.

Any help would be appreciated.

like image 950
user3378165 Avatar asked Sep 04 '18 10:09

user3378165


3 Answers

It is much better to use the svg inline rather than as image. It is also easier to parameterise (e.g. the size):

Icon.jsx

import React from 'react';

export const iconTypes = {
  arrowRight: 'ARROW_RIGHT',
  arrowLeft: 'ARROW_LEFT',
}

export default function Icon({ type = iconTypes.arrowRight, size = 512 }) {
  return (
    <svg
      width={size}
      height={size}
      viewBox='0 0 512 512'>
      {type === iconTypes.arrowRight &&
        <path d='M310.627 438.627l160-160c12.497-12.496 12.497-32.758 0-45.255l-160-160c-12.497-12.496-32.758-12.496-45.255 0s-12.497 32.758 0 45.255l105.373 105.373h-306.745c-17.673 0-32 14.327-32 32s14.327 32 32 32h306.745l-105.373 105.373c-6.248 6.248-9.372 14.438-9.372 22.627s3.124 16.379 9.372 22.627c12.497 12.497 32.758 12.497 45.255 0z' />
      }
      {type === iconTypes.arrowLeft &&
        <path d="..." />
      }
    </svg>
  )
};

Note: you should leave the viewBox prop hardcoded 512 to make the scale work properly.

like image 79
gazdagergo Avatar answered Oct 10 '22 19:10

gazdagergo


I think the best way to show default icon in your application is sprite them and use them with their class name. With that, you can cache and have a better performance.

<Icon name="plus" size={10} />

there are many free tools to sprite your image.

like image 24
Alireza Yadegari Avatar answered Oct 10 '22 18:10

Alireza Yadegari


Can you use the SVG as a background style on a class and just switch them out depending on what icon you need?

For good performance you can just base64 encode the SVG and paste the contents in a background style in your CSS. http://b64.io/ this is a good site for encoding SVGs

E.g.

.kiwi {
  background-image: url("data:image/svg+xml;base64,PD94b...");
}

Any questions, shout!

like image 25
sij_a Avatar answered Oct 10 '22 18:10

sij_a