SVG usa tag e ReactJS

114

Normalmente, para incluir a maioria dos meus ícones SVG que exigem um estilo simples, eu faço:

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

Agora estou brincando com ReactJS ultimamente, avaliando-o como um possível componente em minha nova pilha de desenvolvimento de front-end, no entanto, percebi que em sua lista de tags / atributos suportados, nem useou xlink:hrefsão suportados.

É possível usar sprites svg e carregá-los desta forma no ReactJS?

Ryanzec
fonte
28
Para futuros visitantes, agora você pode usar <use xlinkHref="/svg/svg-sprite#my-icon" />.
David Gilbertson de
6
xlink:hrefestá obsoleto, agora deve ser usado apenas href- developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
Matt Greer
2
@MattGreer Em 2018, o Safari ainda precisa, xlink:hrefentão ainda precisamos usá-lo. Os aplicativos da web reais precisam usar o denominador comum dos recursos do navegador ou implementar soluções alternativas / polyfills específicos.
Tobia
Estou apenas adicionando este comentário para ajudar outras pessoas que procuram esse erro, que foi resolvido pela resposta de Jon Surrell abaixo:Property 'xlink' does not exist on type 'SVGProps<SVGImageElement>
Joe M

Respostas:

50

Atualização de setembro de 2018 : esta solução está obsoleta, leia a resposta de Jon .

-

O React não suporta todas as tags SVG, como você diz, há uma lista de tags suportadas aqui . Eles estão trabalhando em um suporte mais amplo, por exemplo, neste tíquete .

Uma solução alternativa comum é injetar HTML em vez de tags não suportadas, f.ex:

render: function() {
    var useTag = '<use xlink:href="https://stackoverflow.com/svg/svg-sprite#my-icon" />';
    return <svg dangerouslySetInnerHTML={{__html: useTag }} />;
}
David Hellsing
fonte
19
Não, não use dangerouslySetInnerHTML. Você pode usar xlinkHrefconforme mencionado abaixo.
Tobia
O autor provavelmente deve remover esta como a resposta aceita
Aquasar
267

MDN diz que xlink:href está obsoleto em favor de href. Você deve ser capaz de usar o hrefatributo diretamente. O exemplo abaixo inclui ambas as versões.

A partir do React 0.14 , xlink:hrefestá disponível via React como propriedade xlinkHref. É mencionado como um dos "aprimoramentos notáveis" nas notas de versão do 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>

Atualização 09/06/2018: informações adicionadas sobre atributos hrefvs xlink:hrefe exemplo atualizado para incluir ambos. Obrigado @devuxer

Atualização 3 : no momento em que este artigo foi escrito, as propriedades SVG master do React podem ser encontradas aqui .

Atualização 2 : Parece que todos os atributos svg devem agora estar disponíveis via react (consulte o atributo svg PR ).

Atualização 1 : você pode querer ficar de olho no problema relacionado ao svg no GitHub para obter suporte adicional a SVG. Há desenvolvimentos em andamento.

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>

Jon Surrell
fonte
2
> Atualização em 25 de dezembro de 2015: Parece que todos os atributos svg agora devem estar disponíveis via react (consulte o atributo svg PR mesclado). Existe uma maneira padrão de usar esses atributos svg? Serão todos revestidos de camelo, como no caso de xlink: href => xlinkHref?
majorBummer
@majorBummer, dê uma olhada aqui
Jon Surrell
2
essa realmente precisa ser a resposta correta, especialmente quando a resposta atual escolhida recomenda
hazouslySetInnerHTML
1
De acordo com o MDN ( developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href ), xlink:hreffoi preterido e a recomendação é usar hrefsem o prefixo de namespace. (Observe, no entanto, que se você estiver usando TypeScript, as tipificações ainda não foram atualizadas para refletir isso.)
devuxer
No momento em que este artigo foi escrito, xlink: href era compatível com o Safari, mas href não.
neoncube
7

Se você encontrar xlink:href, em seguida, você pode obter o equivalente em ReactJS através da remoção do cólon e camelcasing o texto acrescentou: xlinkHref.

Você provavelmente usará outras tags de namespace em SVG, como xml:space, etc. A mesma regra se aplica a eles (ou seja, xml:spacetorna-se xmlSpace).

HoldOffHunger
fonte
6

Como já foi dito na resposta de Jon Surrell, use-tags agora. Se não estiver usando JSX, você pode implementá-lo assim:

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

Criei um pequeno ajudante que contorna esse problema: https://www.npmjs.com/package/react-svg-use

primeiro npm i react-svg-use -Sentão simplesmente

import Icon from 'react-svg-use'

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

e isso irá gerar a seguinte marcação

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

Os SVGs podem ser importados e usados ​​diretamente como um componente React em seu código 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
fonte