Incorporando SVG ao ReactJS


127

É possível incorporar a marcação SVG em um componente ReactJS?

render: function() {
  return (
    <span>
      <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmln ...
    </span>
  );
}

Resultados no erro:

Os atributos do espaço para nome não são suportados. ReactJSX não é XML.

Qual é a maneira mais leve de fazer isso? Usar algo como React ART é um exagero para o que estou tentando fazer.


1
Você pode criar um jsbin? Pode ser tão simples quanto alterar sua tag SVG de abertura para apenas <svg id="Layer_1">(ou melhor ainda, sem o ID). Edit: aqui está um exemplo: jsbin.com/nifemuwi/2/edit?js,output
— Brigand

@FakeRainBrigand Thanks! Era simples assim neste caso. Veja a resposta de Ben. É bom saber que você pode contornar a análise de jsx quando precisar.
— Nicholas

Respostas:


178

Atualização 2016-05-27

A partir do React v15, o suporte ao SVG no React é (próximo a?) 100% de paridade com o suporte atual do navegador ao SVG ( origem ). Você só precisa aplicar algumas transformações de sintaxe para torná-lo compatível com JSX, como você já precisa fazer para HTML ( class→ className, style="color: purple"→ style={{color: 'purple'}}). Para qualquer atributo com espaço para nome (separado por dois pontos), por exemplo xlink:href, remova :e coloque em maiúscula a segunda parte do atributo, por exemplo xlinkHref. Aqui está um exemplo de uma SVG com <defs>, <use>e estilos inline:

function SvgWithXlink (props) {
    return (
        <svg
            width="100%"
            height="100%"
            xmlns="http://www.w3.org/2000/svg"
            xmlnsXlink="http://www.w3.org/1999/xlink"
        >
            <style>
                { `.classA { fill:${props.fill} }` }
            </style>
            <defs>
                <g id="Port">
                    <circle style={{fill:'inherit'}} r="10"/>
                </g>
            </defs>

            <text y="15">black</text>
            <use x="70" y="10" xlinkHref="#Port" />
            <text y="35">{ props.fill }</text>
            <use x="70" y="30" xlinkHref="#Port" className="classA"/>
            <text y="55">blue</text>
            <use x="0" y="50" xlinkHref="#Port" style={{fill:'blue'}}/>
        </svg>
    );
}

Demonstração de código de trabalho

Para obter mais detalhes sobre suporte específico, consulte a lista de documentos de atributos SVG suportados . E aqui está o problema (agora fechado) do GitHub que rastreia o suporte a atributos SVG com espaço para nome.


Resposta anterior

Você pode fazer uma incorporação simples do SVG sem precisar usar dangerouslySetInnerHTMLapenas os atributos de espaço para nome. Por exemplo, isso funciona:

        render: function() {
            return (
                <svg viewBox="0 0 120 120">
                    <circle cx="60" cy="60" r="50"/>
                </svg>
            );
        }

Nesse ponto, você pode pensar em adicionar adereços como fill, ou qualquer outra coisa que possa ser útil para configurar.


@ChinonsoChukwuogor Great question! Não sei, nunca usei o React Native. Você experimentou?
— Andrew Patton

@AndrewPatton Vários nomes de classe Css com o tick char não funcionam: ' .class1, .class2{fill: #005baa;}' Como posso corrigir isso?
— HelloWorld

@ HelloWorld Você pode me dar um exemplo em que não funciona? Eu só bifurcada minha demonstração original para adicionar classBe funcionou: codepen.io/acusti/pen/BVJzNg
— Andrew Patton

Obrigado, a partir disso, eu consegui importar um svg do arquivo como um componente React sem nenhum carregador, apenas removi `` xmlns: osb = " openswatchbook.org/uri/2009/osb " `` `de a tag svg, deixando apenas os xlmns. É tudo sobre a análise de tags aparentemente. Por precaução, também segui estas etapas: blog.logrocket.com/how-to-use-svgs-in-react
— Funder

56

Se você apenas possui uma sequência svg estática que deseja incluir, pode usar dangerouslySetInnerHTML:

render: function() {
    return <span dangerouslySetInnerHTML={{__html: "<svg>...</svg>"}} />;
}

e o React incluirá a marcação diretamente sem processá-la.


3
Estou controlando alguns caminhos dentro do SVG usando o React, mas o React parece não suportar os elementos de filtro. Existe uma maneira de apoiar isso? Parece que perigosamente o SetInnerHTML não funcionará porque não posso colocar uma extensão dentro de um SVG e não posso usá-lo para definir o atributo de filtro nos caminhos. Suponho que não há uma maneira de criar elementos React como de costume, mas eles passam todos os atributos literalmente para os elementos DOM?
— Andy

Em 2019, parece que você pode usar o SetInnerHTML perigosamente, mas ainda não consegui fazer o filtro de sombra funcionar no Chrome usando o SetInnerHTML perigosamente, mas está funcionando no Firefox.
— Shnd 25/05/19

31

De acordo com um desenvolvedor de reagentes , você não precisa do espaço para nome xmlns. Se você precisar do atributoxlink:href poderá usar xlinkHref a partir de react 0.14

Exemplo

Icon = (props) => {
  return <svg className="icon">
    <use xlinkHref={ '#' + props.name }></use>
  </svg>;
}

12

Se você deseja carregá-lo a partir de um arquivo, tente usar o React-inlinesvg - isso é bastante simples e direto.

import SVG from 'react-inlinesvg';

<SVG
  src="/path/to/myfile.svg"
  preloader={<Loader />}
  onLoad={(src) => {
    myOnLoadHandler(src);
  }}
>
  Here's some optional content for browsers that don't support XHR or inline
  SVGs. You can use other React components here too. Here, I'll show you.
  <img src="/path/to/myfile.png" />
</SVG>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.