131
votes

So normally to include most of my SVG icons that require simple styling, I do:

<svg>
    <use xlink:href="/svg/svg-sprite#my-icon" />
</svg>

Now I have been playing with ReactJS as of late evaluating it as a possible component in my new front-end development stack however I noticed that in its list of supported tags/attributes, neither use or xlink:href are supported.

Is it possible to use svg sprites and load them in this way in ReactJS?

6
For future visitors, you can now use <use xlinkHref="/svg/svg-sprite#my-icon" />.David Gilbertson
xlink:href is deprecated, now supposed to just use href -- developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:hrefMatt Greer
@MattGreer As of 2018, Safari still needs xlink:href so we still need to use it. Actual web applications need to either use the common denominator of browser features, or implement specific workarounds / polyfills.Tobia
I'm just adding this comment to help others who search for this error, which was solved by Jon Surrell's answer below: Property 'xlink' does not exist on type 'SVGProps<SVGImageElement>Joe M
Hey, maybe accept a different answer? Community seems to be agreed about that. Just a helpful suggestion, thanks.HoldOffHunger

6 Answers

294
votes

MDN says that xlink:href is deprecated in favor of href. You should be able to use the href attribute directly. The example below includes both versions.

As of React 0.14, xlink:href is available via React as the property xlinkHref. It is mentioned as one of the "notable enhancements" in the release notes for 0.14.

<!-- REACT JSX: -->
<svg>
  <use xlinkHref='/svg/svg-sprite#my-icon' />
</svg>

<!-- RENDERS AS: -->
<svg>
  <use xlink:href="/svg/svg-sprite#my-icon"></use>
</svg>

Update 2018-06-09: Added info about href vs xlink:href attributes and updated example to include both. Thanks @devuxer

Update 3: At time of writing, React master SVG properties can be found here.

Update 2: It appears that all svg attributes should now be available via react (see merged svg attribute PR).

Update 1: You may want to keep an eye on the svg related issue on GitHub for additional SVG support landing. There are developments in the works.

Demo:

const svgReactElement = (
  <svg
    viewBox="0 0 1340 667"
    width="100"
    height="100"
  >
    <image width="667" height="667" href="https://i.imgur.com/w7GCRPb.png"/>
    { /* Deprecated xlink:href usage */ }
    <image width="667" height="667" x="673" xlinkHref="https://i.imgur.com/w7GCRPb.png"/>
  </svg>
);

var resultHtml = ReactDOMServer.renderToStaticMarkup(svgReactElement);
document.getElementById('render-result-html').innerHTML = escapeHtml(resultHtml);

ReactDOM.render(svgReactElement, document.getElementById('render-result') );

function escapeHtml(unsafe) { return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom-server.browser.development.js"></script>

<h2>Render result of rendering:</h2>
<pre>&lt;svg
  viewBox=&quot;0 0 1340 667&quot;
  width=&quot;100&quot;
  height=&quot;100&quot;
&gt;
  &lt;image width=&quot;667&quot; height=&quot;667&quot; href=&quot;https://i.imgur.com/w7GCRPb.png&quot;/&gt;
  { /* Deprecated xlink:href usage */ }
  &lt;image width=&quot;667&quot; height=&quot;667&quot; x=&quot;673&quot; xlinkHref=&quot;https://i.imgur.com/w7GCRPb.png&quot;/&gt;
&lt;/svg&gt;</pre>

<h2><code>ReactDOMServer.renderToStaticMarkup()</code> output:</h2>
<pre id="render-result-html"></pre>
<h2><code>ReactDOM.render()</code> output:</h2>
<div id="render-result"></div>
50
votes

Update september 2018: this solution is deprecated, read Jon’s answer instead.

--

React doesn’t support all SVG tags as you say, there is a list of supported tags here. They are working on wider support, f.ex in this ticket.

A common workaround is to inject HTML instead for non-supported tags, f.ex:

render: function() {
    var useTag = '<use xlink:href="/svg/svg-sprite#my-icon" />';
    return <svg dangerouslySetInnerHTML={{__html: useTag }} />;
}
10
votes

If you encounter xlink:href, then you can get the equivalent in ReactJS by removing the colon and camelcasing the added text: xlinkHref.

You'll probably eventually be using other namespace-tags in SVG, like xml:space, etc.. The same rule applies to them (i.e., xml:space becomes xmlSpace).

6
votes

As already said in Jon Surrell's answer, use-tags are supported now. If you are not using JSX, you can implement it like this:

React.DOM.svg( { className: 'my-svg' },
    React.createElement( 'use', { xlinkHref: '/svg/svg-sprite#my-icon' }, '' )
)
1
votes

I created a little helper that works around this issue: https://www.npmjs.com/package/react-svg-use

first npm i react-svg-use -S then simply

import Icon from 'react-svg-use'

React.createClass({
  render() {
    return (
      <Icon id='car' color='#D71421' />
    )
  }
})

and this will then generate the following markup

<svg>
  <use xlink:href="#car" style="fill:#D71421;"></use>
</svg>
0
votes

I had problems with showing SVG in Gutenberg block, by referencing it with xlink:href. We used xlinkHref property in react, but after compiling, instead to render as xlink:href it was rendered to xlinkhref, and SVG was not displayed. After a lot of examining, I found out that xlink:href is deprecated (although it worked if we add it in html, or directly in chrome dev tools), and that href should be used instead. So after changing it to href it worked.

"SVG 2 removed the need for the xlink namespace, so instead of xlink:href you should use href." https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href

This is the code I used

SVG file

<svg id="svg-source" style="display: none;" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
    <symbol id="svg-arrow-accordion" viewBox="0 0 15 24" fill="none">
        <path id="Path_1662" data-name="Path 1662" d="M15.642,14.142h-3V1.5H0v-3H15.642Z" transform="translate(2 2) rotate(45)" fill="currentColor"></path>
    </symbol>
</svg>

React file

<svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="15" height="24">
<use href="#svg-arrow-accordion"></use>
</svg>