React SVG Component
react-svg is a React component designed to fetch SVG files from a given URL and inject their raw markup directly into the DOM, rather than rendering them as `<img>` tags. This approach, powered by the underlying `@tanem/svg-injector` library, enables full manipulation of the SVG's internal elements via CSS and JavaScript, unlocking possibilities like dynamic styling, animation, and interactivity that are not possible with traditional `<img>` elements. It also features client-side caching of fetched SVGs to reduce redundant network requests for repeated assets. The package is actively maintained, with its current stable version being 17.2.4, and exhibits a healthy release cadence, often seeing updates within a three-month window. It ships with TypeScript type definitions, enhancing development in TypeScript environments.
Common errors
-
Failed to load resource: net::ERR_FAILED
cause The `src` prop points to an SVG file that cannot be found or accessed by the browser, often due to an incorrect path or server issue.fixVerify the `src` URL is correct and the SVG file exists at that location. Check network requests in browser developer tools for the exact HTTP status code. -
Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
cause The SVG is being requested from a different origin (domain, protocol, or port) than the current page, and the server hosting the SVG does not send the necessary `Access-Control-Allow-Origin` HTTP header.fixConfigure the server hosting the SVG to send appropriate CORS headers that allow requests from your application's origin. For local development, a Webpack proxy or a browser extension might bypass this, but a server-side fix is essential for production. -
Error: Objects are not valid as a React child (found: object with keys {$$typeof, type, props, ref}). If you meant to render a collection of children, use an array instead. / Or: Invariant Violation: React.Children.only expected to receive a single React element child.cause Attempting to pass raw SVG markup as a string directly to the `src` prop or as children to `ReactSVG`, which expects a URL.fixThe `src` prop requires a URL string. If you have SVG markup as a string, you must store it as a file and provide its URL, or manually parse and inject it into the DOM outside of `ReactSVG`. -
SVG rendering not working / SVG not visible / broken appearance
cause The SVG is loaded but not displayed correctly due to CSS conflicts, incorrect dimensions, or issues within the SVG markup itself (e.g., missing viewBox, inline styles, or namespace issues when bundled with tools like `@svgr/webpack`).fixInspect the injected SVG in the browser's developer tools. Check its dimensions, applied CSS, and the integrity of its internal structure. Ensure `viewBox` is set correctly in the SVG. If using a bundler like Webpack with SVGR, ensure it's configured to output a compatible format or handle namespace tags correctly.
Warnings
- gotcha Directly injecting SVG markup (e.g., as a string literal) via the `src` prop is not supported. The `src` prop expects a URL to an SVG file. If you have SVG markup as a string, consider using `dangerouslySetInnerHTML` with appropriate sanitization or a direct DOM manipulation approach.
- breaking When fetching SVGs from a different origin (domain, protocol, or port), Cross-Origin Resource Sharing (CORS) policies must be correctly configured on the server hosting the SVG. Without proper CORS headers, the browser will block the resource request, preventing `react-svg` from injecting the SVG.
- security SVGs can contain embedded scripts (`<script>` tags or event handlers) that, when injected into the DOM, can execute JavaScript. The `evalScripts` prop is designed to control this behavior and defaults to 'never'. Changing this to 'once' or 'always' can introduce Cross-Site Scripting (XSS) vulnerabilities if the SVG content is untrusted or user-supplied.
- gotcha Changing the `src` prop of a `ReactSVG` component will trigger a re-injection of the SVG. This re-injection process involves removing the old SVG and inserting the new one, which can cause a brief visual 'flash' as the content is swapped.
- gotcha To ensure proper accessibility, especially for screen readers, always provide meaningful `title` and `desc` props for your SVGs, particularly if they convey important information. These props inject `<title>` and `<desc>` elements into the SVG, enhancing its semantic understanding.
Install
-
npm install react-svg -
yarn add react-svg -
pnpm add react-svg
Imports
- ReactSVG
const ReactSVG = require('react-svg')import { ReactSVG } from 'react-svg' - ReactSVGProps
import type { ReactSVGProps } from 'react-svg' - SVGInjector
import { SVGInjector } from '@tanem/svg-injector'
Quickstart
import { createRoot } from 'react-dom/client';
import { ReactSVG } from 'react-svg';
const rootElement = document.getElementById('root');
if (rootElement) {
const root = createRoot(rootElement);
root.render(
<div>
<h1>My Application</h1>
<p>Loading an external SVG using ReactSVG:</p>
<ReactSVG
src="/path/to/your/image.svg"
beforeInjection={(svg) => {
console.log('SVG about to be injected:', svg.id);
svg.setAttribute('style', 'width: 100px; height: 100px;');
}}
afterInjection={(svg) => console.log('SVG injected:', svg.id)}
onError={(error) => console.error('Error loading SVG:', error.message)}
loading={() => <span style={{ color: 'blue' }}>Loading SVG...</span>}
fallback={() => <span style={{ color: 'red' }}>Could not load SVG</span>}
/>
<p>Ensure 'image.svg' is accessible at the specified path.</p>
</div>
);
} else {
console.error("Root element 'root' not found.");
}