Etiqueta de uso SVG y ReactJS

114

Entonces, normalmente para incluir la mayoría de mis íconos SVG que requieren un estilo simple, lo hago:

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

Ahora he estado jugando con ReactJS en los últimos tiempos la evaluación como un posible componente en mi nueva pila de desarrollo front-end sin embargo, me di cuenta de que en su lista de etiquetas / atributos soportados, ni useo xlink:hrefson compatibles.

¿Es posible usar sprites svg y cargarlos de esta manera en ReactJS?

Ryanzec
fuente
28
Para futuros visitantes, ahora puede usar <use xlinkHref="/svg/svg-sprite#my-icon" />.
David Gilbertson
6
xlink:hrefestá en desuso, ahora se supone que solo debe usar href- developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
Matt Greer
2
@MattGreer A partir de 2018, Safari aún lo necesita, xlink:hrefpor lo que aún necesitamos usarlo. Las aplicaciones web reales deben utilizar el denominador común de las funciones del navegador o implementar soluciones / polyfills específicos.
Tobia
Solo estoy agregando este comentario para ayudar a otros que buscan este error, que fue resuelto por la respuesta de Jon Surrell a continuación:Property 'xlink' does not exist on type 'SVGProps<SVGImageElement>
Joe M

Respuestas:

50

Actualización de septiembre de 2018 : esta solución está obsoleta, lea la respuesta de Jon en su lugar.

-

React no admite todas las etiquetas SVG como usted dice, hay una lista de etiquetas compatibles aquí . Están trabajando en un soporte más amplio, p. Ej. En este ticket .

Una solución alternativa común es inyectar HTML en lugar de etiquetas no compatibles, f.ex:

render: function() {
    var useTag = '<use xlink:href="https://stackoverflow.com/svg/svg-sprite#my-icon" />';
    return <svg dangerouslySetInnerHTML={{__html: useTag }} />;
}
David Hellsing
fuente
19
No, no lo use dangerouslySetInnerHTML. Puede utilizar xlinkHrefcomo se menciona a continuación.
Tobia
El autor probablemente debería eliminar esto como la respuesta aceptada
Aquasar
267

MDN dice que xlink:href está en desuso a favor de href. Debería poder utilizar el hrefatributo directamente. El siguiente ejemplo incluye ambas versiones.

A partir de React 0.14 , xlink:hrefestá disponible a través de React como propiedad xlinkHref. Se menciona como una de las "mejoras notables" en las notas de la versión de 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>

Actualización 2018-06-09: se agregó información sobre los atributos hrefvs xlink:hrefy un ejemplo actualizado para incluir ambos. Gracias @devuxer

Actualización 3 : En el momento de escribir este artículo, las propiedades de React master SVG se pueden encontrar aquí .

Actualización 2 : Parece que todos los atributos svg ahora deberían estar disponibles a través de react (ver PR del atributo svg fusionado ).

Actualización 1 : es posible que desee estar atento al problema relacionado con svg en GitHub para obtener más compatibilidad con SVG. Hay novedades en proceso.

Manifestación:

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
fuente
2
> Actualización 25 de diciembre de 2015: parece que todos los atributos svg ahora deberían estar disponibles a través de react (ver PR del atributo svg fusionado). ¿Existe una forma estándar de utilizar estos atributos svg? ¿Serán todos en caja de camello como en el caso de xlink: href => xlinkHref?
majorBummer
@majorBummer echa un vistazo aquí
Jon Surrell
2
esta realmente debe ser la respuesta correcta, especialmente cuando la respuesta elegida actual recomienda dangerouslySetInnerHTML, que es, bueno, peligroso
feihcsim
1
Según MDN ( developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href ), xlink:hrefha quedado obsoleto y la recomendación es utilizarlo hrefsin el prefijo de espacio de nombres. (Nótese, sin embargo, si usted está utilizando mecanografiado, las tipificaciones todavía no se han actualizado para reflejar esto.)
devuxer
En el momento de escribir este artículo, xlink: href es compatible con Safari, pero href no.
neoncube
7

Si se encuentra xlink:href, entonces se puede obtener el equivalente en ReactJS por la extirpación del colon y camelCasing el texto añadido: xlinkHref.

Probablemente eventualmente usará otras etiquetas de espacio de nombres en SVG, como xml:space, etc. La misma regla se aplica a ellos (es decir, se xml:spaceconvierte en xmlSpace).

HoldOffHunger
fuente
6

Como ya se dijo en la respuesta de Jon Surrell, las etiquetas de uso ahora son compatibles. Si no está utilizando JSX, puede implementarlo así:

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

Creé un pequeño ayudante que soluciona este problema: https://www.npmjs.com/package/react-svg-use

primero npm i react-svg-use -Sluego simplemente

import Icon from 'react-svg-use'

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

y esto generará el siguiente marcado

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

Los SVG se pueden importar y usar directamente como un componente de React en su código de 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
fuente