Búsqueda de sitios web

javascript - Insertar SVG en ReactJS


¿Es posible incrustar código SVG en un componente de ReactJS?

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

Resultados en el error:

Los atributos de espacio de nombres no son compatibles. ReactJSX no es XML.

¿Cuál es la forma más ligera de hacer esto? Usar algo como React ART es demasiado excesivo para lo que estoy tratando de hacer.

Respuesta #1

Actualización 27-05-2016

A partir de React v15, el soporte para SVG en React es (¿casi?) del 100% en comparación con el soporte actual de los navegadores para SVG (fuente). Solo necesitas aplicar algunas transformaciones de sintaxis para que sea compatible con JSX, como ya tienes que hacer para HTML (class → className, style="color: purple" → style={{color: 'purple'}}). Para cualquier atributo con espacio de nombres (separado por dos puntos), por ejemplo xlink:href, elimina el : y convierte en mayúscula la segunda parte del atributo, por ejemplo xlinkHref. Aquí hay un ejemplo de un svg con <defs>, <use> y estilos en línea:

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

Demostración de Codepen funcional

Para más detalles sobre soporte específico, consulta la lista de atributos SVG soportados en la documentación. Y aquí está el (ahora cerrado) problema de GitHub que hizo seguimiento del soporte para atributos SVG con espacios de nombres.


Respuesta anterior

Puedes hacer una inserción sencilla de SVG sin tener que usar dangerouslySetInnerHTML simplemente eliminando los atributos de espacio de nombres. Por ejemplo, esto funciona:

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

En ese momento puedes pensar en añadir props como fill, o cualquier otra cosa que pueda ser útil para configurar.

Respuesta #2

Si solo tienes una cadena SVG estática que deseas incluir, puedes usar dangerouslySetInnerHTML:

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

y React incluirá el marcado directamente sin procesarlo en absoluto.

Respuesta #3

Según un desarrollador de React, no necesitas el espacio de nombres xmlns. Si necesitas el atributo xlink:href, puedes usar xlinkHref desde React 0.14

Ejemplo

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

Respuesta #4

Si quieres cargarlo desde un archivo, puedes intentar usar React-inlinesvg; eso es bastante simple y directo.

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>

Artículos relacionados