An SVG loader component for ReactJS

Last update: Jun 17, 2022

react-inlinesvg

NPM version Build Status Maintainability Test Coverage

Load inline, local or remote SVGs in your React components.

Highlights

  • 🏖 Easy to use: Just set the src
  • 🛠 Flexible: Personalize the options to fit your needs
  • ⚡️ Smart: Async requests will be cached.
  • 🚀 SSR: Render a loader until the DOM is available
  • 🟦 Typescript: Nicely typed

Usage

npm i react-inlinesvg

And import it into your code:

import React, { useRef } from 'react';
import SVG, { Props as SVGProps } from 'react-inlinesvg';

const Logo = React.forwardRef<SVGElement, SVGProps>((props, ref) => (
  <SVG innerRef={ref} title="MyLogo" {...props} />
));

export function App() {
  const logo = useRef<SVGElement>(null);

  return (
    <main>
      <SVG src={`${process.env.PUBLIC_URL}/menu.svg`} width={24} height="auto" title="Menu" />
    	<Logo ref={logo} src={`${process.env.PUBLIC_URL}/logo.svg`} />
		</main>
  );
}

Props

src {string} - required.
The SVG file you want to load. It can be a require, URL or a string (base64 or url encoded). If you are using create-react-app and your file resides in the public directory you can use the path directly without require.

baseURL {string}
An URL to prefix each ID in case you are using the <base> tag and uniquifyIDs.

children {ReactNode}
The fallback content in case of a fetch error or unsupported browser.

<SVG src="...">
	<img src="..." alt="fallback" />
</SVG>

cacheRequests {boolean} ▶︎ true
Cache remote SVGs.

description {string}
A description for your SVG. It will override an existing <desc> tag.

innerRef {React.Ref}
Set a ref in SVGElement.

loader {node}
A component to be shown while the SVG is loading.

onError {function}
A callback to be invoked if loading the SVG fails.
This will receive a single argument with:

  • a FetchError with:
{
  message: string;
  type: string;
  errno: string;
  code: string;
}
  • or an InlineSVGError, which has the following properties:
{
    name: 'InlineSVGError',
    data?: object,
    message: string
}

onLoad {function}.
A callback to be invoked upon successful load.
This will receive 2 arguments: the src prop and a hasCache boolean

preProcessor {function} ▶︎ string
A function to process the contents of the SVG text before parsing.

title {string}
A title for your SVG. It will override an existing <title> tag.

uniqueHash {string} ▶︎ a random 8 characters string [A-Za-z0-9]
A string to use with uniquifyIDs.

uniquifyIDs {boolean} ▶︎ false
Create unique IDs for each icon.

Any additional props will be passed down to the SVG element.

Example

<SVG
  baseURL="/home"
  cacheRequests={true}
  description="The React logo"
  loader={<span>Loading...</span>}
  onError={error => console.log(error.message)}
  onLoad={(src, hasCache) => console.log(src, hasCache)}
  preProcessor={code => code.replace(/fill=".*?"/g, 'fill="currentColor"')}
  src="https://cdn.svgporn.com/logos/react.svg"
  title="React"
  uniqueHash="a1f8d1"
  uniquifyIDs={true}
/>

Browser Support

Any browsers that support inlining SVGs and fetch will work.

If you need to support legacy browsers you'll need to include a polyfiil for fetch and Number.isNaN in your app. Take a look at react-app-polyfill or polyfill.io.

CORS

If you are loading remote SVGs, you'll need to make sure it has CORS support.

Why you need this package?

One of the reasons SVGs are awesome is because you can style them with CSS. Unfortunately, this winds up not being too useful in practice because the style element has to be in the same document. This leaves you with three bad options:

  1. Embed the CSS in the SVG document
    • Can't use your CSS preprocessors (LESS, SASS)
    • Can't target parent elements (button hover, etc.)
    • Makes maintenance difficult
  2. Link to a CSS file in your SVG document
    • Sharing styles with your HTML means duplicating paths across your project, making maintenance a pain
    • Not sharing styles with your HTML means extra HTTP requests (and likely duplicating paths between different SVGs)
    • Still can't target parent elements
    • Your SVG becomes coupled to your external stylesheet, complicating reuse.
  3. Embed the SVG in your HTML
    • Bloats your HTML
    • SVGs can't be cached by browsers between pages.
    • A maintenance nightmare

But there's an alternative that sidesteps these issues: load the SVG with a GET request and then embed it in the document. This is what this component does.

Note

The SVG [<use>][svg-use-external-source] element can be used to achieve something similar to this component. See [this article][use-article] for more information and [this table][use-support] for browser support and caveats.

Credits

Thanks to @matthewwithanm for creating this component and so kindly transfer it to me. I'll definitely keep the good work! ❤️

GitHub

https://github.com/matthewwithanm/react-inlinesvg
Comments
  • 1. Remote svg improperly rendered

    I don't think there's much to say about it. Am i completely missing something here?

    Here is the code <SVG src={`${cdn}/icons/${icon}`} /> Here is how it looks image

    Here is how it looks using regular img tag: image

    When i inspect these elements they look completely fine. The whole svg source is correct. I tried filling colors, fitting the objects but no luck.

    Reviewed by demfabris at 2020-12-11 20:13
  • 2. Issue with new types

    In my project I have a custom component that passes in cacheRequests = true for convenience when using this library. It looks like this:

    import * as React from 'react';
    
    import Svg from 'react-inlinesvg';
    import {Props as IProps} from 'react-inlinesvg/lib/types';
    
    const Icon = ({src, cacheRequests = true, ...rest}: IProps ) => (
      <Svg cacheRequests={cacheRequests} src={src} {...rest} />
    );
    
    export default Icon;
    

    Prior to v2.0.1 the above worked fine without errors. However, since v2.0.1 I get an error:

    ERROR in [at-loader] ./src/components/common/Icon/index.tsx:9:4 
        TS2322: Type '{ baseURL?: string | undefined; children?: ReactNode; description?: string | undefined; innerRef?: RefObject<HTMLElement> | ((instance: HTMLElement | null) => void) | null | undefined; ... 365 more ...; src: string; }' is not assignable to type 'IntrinsicClassAttributes<InlineSVG>'.
      Types of property 'ref' are incompatible.
        Type 'string | ((instance: SVGElement | null) => void) | RefObject<SVGElement> | null | undefined' is not assignable to type 'string | ((instance: InlineSVG | null) => void) | RefObject<InlineSVG> | null | undefined'.
          Type '(instance: SVGElement | null) => void' is not assignable to type 'string | ((instance: InlineSVG | null) => void) | RefObject<InlineSVG> | null | undefined'.
            Type '(instance: SVGElement | null) => void' is not assignable to type '(instance: InlineSVG | null) => void'.
              Types of parameters 'instance' and 'instance' are incompatible.
                Type 'InlineSVG | null' is not assignable to type 'SVGElement | null'.
                  Type 'InlineSVG' is missing the following properties from type 'SVGElement': className, ownerSVGElement, viewportElement, addEventListener, and 217 more.
    

    Any ideas of how to fix this? Maybe I'm just missing something silly.

    Thanks!

    Reviewed by AnderssonChristian at 2020-10-28 17:41
  • 3. Caching AJAX requests

    Hi,

    Great thanks for the nice react module, I found it the best among other inline svg loading technics, especially for isomorphic apps.

    But I noticed one issue though, when using multiple SVG images on a page, there's a lot of identical requests for same images:

    image

    What do you think about adding memory cache for previously loaded SVG's? Since SVG's aren't heavy, it should not cause any problems with memory leaks.

    Reviewed by therobhrt at 2015-11-03 10:34
  • 4. Support for React 16

    Basic support for React 16.0:

    • [x] Use enzyme 3 and enzyme-adapter-react-16
    • [x] Install react-test-renderer since enzyme-adapter-react-16 depends on it
    • [x] Added react-dom as a peerDependency, why wasn't it so originally anyway?
    • [x] Added react-dom-factories for the few tests that requires it
    • [x] Update tests to use the adapter and react-dom-factories

    As far as I am concerned there is no way to tell npm that if someone has a peerDependency of 16 then it has to install prop-types otherwise it ignores that (since it will be installed with React pre-16 by default) so I guess the way to go here is to drop support for pre-16 moving forward?

    Closes https://github.com/matthewwithanm/react-inlinesvg/issues/67

    Reviewed by Mathspy at 2017-10-02 20:57
  • 5. Implemented baseURL

    The baseURL allows you to prefix the ID with a baseURL. This is useful when the page has a base tag which in some browsers (e.g. Firefox) will break the URLs when referencing IDs.

    Note, I branched this off https://github.com/gilbarbara/react-inlinesvg/pull/85

    Reviewed by Robinfr at 2018-02-16 09:11
  • 6. After 1.0 def style is stripped off of elements

    After upgrading to 1.0 svg's aren't properly loaded anymore.

    Inside defs for example, fills and strokes are removed from the elements. After some debugging it looks like dom-to-react is the culprit stripping so called "not recognized" attributes, resulting in elements rendered without those attrs.

    https://github.com/gilbarbara/react-inlinesvg/blob/master/src/index.tsx#L257

    At this point node contains all the proper attributes but looking at the result of prepareNode the same attributes are not present on related React node.

    Reviewed by SimoneIrato at 2019-07-21 11:48
  • 7. SVG is not a constructor function for JSX elements

    I get the title error when trying to use the V1.0.0 library in the way defined in the README. I also get another error: JSX element does not support attributes because it does not have a 'props' property.

    I'm not sure if these warnings are accurate, but I cannot compile with Storybook with these changes.

    Apologies if I am seriously off the mark here. I'm extremely new to React and Typescript.

    Screen Shot 2019-07-19 at 17 05 05
    Reviewed by valtism at 2019-07-19 07:09
  • 8. Using react-inlinesvg in an npm package

    When I use react-inlinesvg in an npm package and add it to another project, I get this error. Any ideas how to resolve?

    🚨  ../node_modules/react-inlinesvg/es/index.js: [BABEL] .../node_modules/react-inlinesvg/es/index.js: Unknown option: base.sourceMapRelative. Check out http://babeljs.io/docs/usage/options/ for more information about options.
    
    A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:
    
    Invalid:
      `{ presets: [{option: value}] }`
    Valid:
      `{ presets: [['presetName', {option: value}]] }`
    

    I tried setting .babelrc to

    { "presets": ["react", "es2015"] }
    
    Reviewed by julianguyen at 2018-03-12 22:24
  • 9. Jest snapshots failing due to unique hash

    Jest tests seem to be failing for every test that include react-inlinesvg due to the unique hash not matching. As the hash changes every time the test is run the snapshot does no match. Is there a way of testing this without breaking tests? Attached is an image of the failing snapshot test.

    screenshot from 2017-11-27 11-54-33

    Reviewed by nialloc9 at 2017-11-27 11:58
  • 10. Extra characters ]> added to the span tag

    Hi,

    I'm getting a couple of extra characters "]>" added to the span tag.

    Here's the code:

    var Isvg = require('react-inlinesvg');
    <Isvg src="./img/icons/my-icon.svg"></Isvg>
    

    The output is as follow:

    <span class="isvg loaded" data-reactid=".0.1.2.0">
       <!--?xml version="1.0" encoding="utf-8"?-->
       <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
       ]>
       <svg>
          ...
       </svg>
    </span>
    

    Do you have any idea why this extra characters appears?

    Cheers!

    Reviewed by ameego at 2015-06-24 11:16
  • 11. Assigning svg a className or attribute

    @matthewwithanm is there a way to give the actual svg a className or attribute? Reason being when I use something like GSAP for tweening, it's necessary for me to reference the actual svg for animation.

    Reviewed by ChrisSki at 2014-09-30 14:37
🎉 基于 reactjs 开发的可视化项目实战

?? 基于 reactjs 开发的可视化项目实战

Jun 13, 2022
Calculadora simples usando classes do ReactJS

React Calc This calculator was developed by me using ReactJS during my JavaScript studies.

Jun 23, 2021
Projeto desenvolvido durante a NLW #06, apresentado pela Rocketseat entre 20 a 27 de Junho de 2021. 💜 #NLW #ReactJS #Rocketseat

?? Projeto Let Me Ask é um projeto desenvolvido durante a Next Level Week #6, apresentado pela Rocketseat entre 20 a 27 de Junho de 2021. ?? Aula 1 Au

Jun 29, 2021
Projeto desenvolvido na missão ReactJS no NLW #06

?? Tecnologias Esse projeto foi desenvolvido com as seguintes tecnologias: React Firebase TypeScript ?? Como executar Clone o projeto e acesse a pasta

Jun 17, 2022
Consuming GitHub API, showing user's profile and repositories, with ReactJS
Consuming GitHub API, showing user's profile and repositories, with ReactJS

GitHubProfiles Project made with ReactJS to practice API consuming using GitHub API, in order to show in a simple way user's profile and repositories.

Jun 16, 2022
Imersão Alura - 3º Edição. Criando o Alurakut, baseado no antigo Orkut. Usando ReactJs, NextJs e StyledComponents, em um semana de muito aprendizado.
Imersão Alura - 3º Edição. Criando o Alurakut, baseado no antigo Orkut. Usando ReactJs, NextJs e StyledComponents, em um semana de muito aprendizado.

????‍♀️ ?? Cuidado - Obras em andamento ?? Olá pessoa, seja bem vindo ao Alurakut da Ana Esse tem a minha carinha, mas você pode ter o seu também! O A

Mar 7, 2022
Projeto desenvolvido na missão ReactJS no NLW #06

?? Tecnologias Esse projeto foi desenvolvido com as seguintes tecnologias: React Firebase TypeScript ?? Como executar Clone o projeto e acesse a pasta

Aug 23, 2021
Reactjs Pokedex application

This project was bootstrapped with Create React App, using the Redux and Redux Toolkit template. Available Scripts In the project directory, you can r

Jun 15, 2022
This project is collection of large projects's source code (codebases), built with Reactjs. Eg: Bestbuy, Postman, Trello, Udacity, Coursera, Skillshare, Invision, Intercom, Pipedrive, ... and more.
This project is collection of large projects's source code (codebases), built with Reactjs. Eg: Bestbuy, Postman, Trello, Udacity, Coursera, Skillshare, Invision, Intercom, Pipedrive, ... and more.

This project is collection of large projects's source code (codebases), built with Reactjs. Eg: Bestbuy, Postman, Trello, Udacity, Coursera, Skillshare, Invision, Intercom, Pipedrive, ... and more.

Jun 22, 2022
Reactjs Speed typing game
Reactjs Speed typing game

Reactjs Speed typing game

Mar 22, 2022
Sistema de páginas integradas feitas com Reactjs

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Jan 22, 2022
List of top 500 ReactJS Interview Questions & Answers....Coding exercise questions are coming soon!!
List of top 500 ReactJS Interview Questions & Answers....Coding exercise questions are coming soon!!

React Interview Questions & Answers Click ⭐ if you like the project. Pull Request are highly appreciated. Follow me @SudheerJonna for technical update

Jun 15, 2022
A Magic Memory Game Built with ReactJS

A Magic Memory Game Built with ReactJS

Jun 11, 2022
Brainn challenge with ReactJs, Typescript, Redux and Cypress.
Brainn challenge with ReactJs, Typescript, Redux and Cypress.

Exercício de Front-end Introdução A proposta do exercício de front-end da Brainn é ser simples e divertido. Exercício O objetivo é construir uma aplic

Nov 9, 2021
📜 Spacetraveling é blog que foi desenvolvido como desafio no Ignite da trilha de ReactJs da Rocketseat.
📜 Spacetraveling é blog que foi desenvolvido como desafio no Ignite da trilha de ReactJs da Rocketseat.

SpaceTraveling - Next.js Aplicação em formato de blog utilizando Prismic CMS ?? Sobre o projeto O projeto tem como objetivo o estudo e desenvolvimento

Dec 14, 2021
Estudo de ReactJS curso da Digital Innovation One

Práticas Avançadas em Projetos com ReactJS Repositório de estudo de ReactJS Ciclo de Vida do React - Aulas 01 a 03 Entendendo o ciclo de vida do React

Nov 4, 2021
Pokédex criada com Reactjs
Pokédex criada com Reactjs

Objetivo • Preview • Funcionalidades • Tecnologias utilizadas • Instalação • ?? Objetivo ?? Projeto desenvolvido para fins de estudo da biblioteca Rea

Apr 24, 2022
This is a example for integrating PayHere with ReactJS

PayHere React JS example demo This is a example for integrating PayHere with ReactJS Steps Clone the project npm install How to perform your own React

Nov 24, 2021
This is the ReactJS Disney Plus Clone

Disney Plus Clone Readme LIVE DEMO ?? Watch full tutorial HERE Description This is the ReactJS Disney Plus Clone, the perfect project to put on your p

Feb 26, 2022