SVG use tag et ReactJS

114

Donc, normalement, pour inclure la plupart de mes icônes SVG qui nécessitent un style simple, je fais:

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

Maintenant, j'ai joué avec ReactJS récemment en l'évaluant comme un composant possible dans ma nouvelle pile de développement front-end, mais j'ai remarqué que dans sa liste de balises / attributs pris en charge, ni l'un useni l' autre ne xlink:hrefsont pris en charge.

Est-il possible d'utiliser des sprites svg et de les charger de cette manière dans ReactJS?

Ryanzec
la source
28
Pour les futurs visiteurs, vous pouvez désormais utiliser <use xlinkHref="/svg/svg-sprite#my-icon" />.
David Gilbertson
6
xlink:hrefest obsolète, maintenant censé simplement utiliser href- developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
Matt Greer
2
@MattGreer À partir de 2018, Safari en a encore besoin xlink:href, nous devons donc encore l'utiliser. Les applications Web réelles doivent soit utiliser le dénominateur commun des fonctionnalités du navigateur, soit implémenter des solutions de contournement / polyfills spécifiques.
Tobia
J'ajoute simplement ce commentaire pour aider les autres qui recherchent cette erreur, qui a été résolue par la réponse de Jon Surrell ci-dessous:Property 'xlink' does not exist on type 'SVGProps<SVGImageElement>
Joe M

Réponses:

50

Mise à jour de septembre 2018 : cette solution est obsolète, lisez plutôt la réponse de Jon .

-

React ne prend pas en charge toutes les balises SVG comme vous le dites, il existe une liste des balises prises en charge ici . Ils travaillent sur un support plus large, par exemple dans ce ticket .

Une solution courante consiste à injecter du HTML à la place pour les balises non prises en charge, par exemple:

render: function() {
    var useTag = '<use xlink:href="https://stackoverflow.com/svg/svg-sprite#my-icon" />';
    return <svg dangerouslySetInnerHTML={{__html: useTag }} />;
}
David Hellsing
la source
19
Non, n'utilisez pas dangerouslySetInnerHTML. Vous pouvez utiliser xlinkHrefcomme mentionné ci-dessous.
Tobia
L'auteur devrait probablement supprimer ceci comme réponse acceptée
Aquasar
267

MDN dit que xlink:href c'est déconseillé en faveur de href. Vous devriez pouvoir utiliser l' hrefattribut directement. L'exemple ci-dessous comprend les deux versions.

À partir de React 0.14 , xlink:hrefest disponible via React en tant que propriété xlinkHref. Il est mentionné comme l'une des "améliorations notables" dans les notes de version pour la version 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>

Mise à jour 09/06/2018: Ajout d'informations sur les attributs hrefvs xlink:hrefet exemple mis à jour pour inclure les deux. Merci @devuxer

Mise à jour 3 : Au moment de la rédaction de cet article, les propriétés SVG du maître React peuvent être trouvées ici .

Mise à jour 2 : Il semble que tous les attributs svg devraient maintenant être disponibles via react (voir attribut svg fusionné PR ).

Mise à jour 1 : Vous voudrez peut-être garder un œil sur le problème lié aux svg sur GitHub pour un atterrissage supplémentaire du support SVG. Il y a des développements en cours.

Démo:

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>

Jon Surrell
la source
2
> Mise à jour du 25 décembre 2015: il semble que tous les attributs svg devraient désormais être disponibles via react (voir attribut svg fusionné PR). Existe-t-il une manière standard d'utiliser ces attributs svg? Seront-ils tous camel casé comme dans le cas de xlink: href => xlinkHref?
majorBummer
@majorBummer jetez un oeil ici
Jon Surrell
2
cela doit vraiment être la bonne réponse, surtout lorsque la réponse actuelle choisie recommande dangereusementSetInnerHTML, ce qui est, eh bien, dangereux
feihcsim
1
Selon MDN ( developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href ), xlink:hrefa été déconseillé, et la recommandation est d'utiliser hrefsans le préfixe d'espace de noms. (Notez, cependant, si vous utilisez TypeScript, les typages n'ont pas encore été mis à jour pour refléter cela.)
devuxer
Au moment de la rédaction de cet article, xlink: href est pris en charge dans Safari, mais href ne l'est pas.
neoncube
7

Si vous rencontrez xlink:href, vous pouvez obtenir l'équivalent en ReactJS en supprimant le côlon et notationsCamel le texte ajouté: xlinkHref.

Vous utiliserez probablement éventuellement d'autres balises d'espace de noms dans SVG, comme xml:space, etc. La même règle s'applique à eux (c'est-à-dire xml:spacedevient xmlSpace).

HoldOffHunger
la source
6

Comme déjà dit dans la réponse de Jon Surrell, les balises d'utilisation sont désormais prises en charge. Si vous n'utilisez pas JSX, vous pouvez l'implémenter comme ceci:

React.DOM.svg( { className: 'my-svg' },
    React.createElement( 'use', { xlinkHref: '/svg/svg-sprite#my-icon' }, '' )
)
mhanisch
la source
0

J'ai créé une petite aide qui fonctionne autour de ce problème: https://www.npmjs.com/package/react-svg-use

d'abord npm i react-svg-use -Spuis simplement

import Icon from 'react-svg-use'

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

et cela générera alors le balisage suivant

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

Les SVG peuvent être importés et utilisés directement en tant que composant React dans votre code React.

import React from 'react';
import {ReactComponent as ReactIcon} from './icon.svg';

const App = () => {
  return (
    <div className="App">
      <ReactIcon />
    </div>
  );
}
export default App;
Olcay Özdemir
la source