简体   繁体   中英

SVG use tag and ReactJS

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?

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>

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 }} />;
}

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 (ie, xml:space becomes xmlSpace ).

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' }, '' )
)

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>

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?

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>

This is svg Component.

const SvgComponent = () => {
    return <svg width="0" height="0">
        <defs>
            <symbol id="test" viewBox="0 0 100 100">
                <line x1='0' y1='50' x2='100' y2='50' strokeWidth='8' stroke="#000" />
            </symbol>
        </defs>
    </svg>
}

export default SvgComponent

use component

import SvgComponent from './SvgComponent';

export default function App() {
  return (
    <>
      <SvgComponent/>
      <svg>
        <use xlinkHref="#test"></use>
      </svg>
    </>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM