domingo, 16 de noviembre de 2025

Diferentes maneras de importar un archivo .svg

 Estoy importando un archivo que se llama torta.svg como si fuera un componente de React, a través de SVGR. Dice: InvalidCharacterError: Failed to execute 'createElement' on 'Document': The tag name provided ('http://127.0.0.1:5173/resources/images/torta.svg') is not a valid name.


Este es un error muy común cuando se usa SVGR y Vite, ¡pero es fácil de solucionar!

El mensaje de error indica que React está intentando usar una cadena de texto que contiene la ruta de tu archivo SVG (http://127.0.0.1:5173/.../torta.svg) como si fuera el nombre de un componente JSX.

Esto sucede porque Vite y SVGR exponen el SVG de dos maneras distintas, y probablemente estás usando la exportación por defecto, que es la URL del archivo, en lugar de la exportación nombrada, que es el componente React en sí.

La Solución: Usar la Exportación Nombrada (ReactComponent)

Cuando instalaste vite-plugin-svgr, este configuró la importación para darte dos cosas:

  1. Exportación por defecto: La URL/ruta del archivo (un string). Útil si quieres pasarla a un <img> o una función de fondo CSS.

  2. Exportación nombrada (ReactComponent): El componente funcional de React (la función que devuelve JSX). Esto es lo que quieres.

Debes cambiar cómo importas el archivo, utilizando un alias para ReactComponent:

Aquí tienes un ejemplo del componente corrigiendo el error:

Uso Correcto de SVG con SVGR

import React from 'react';
// IMPORTACIÓN INCORRECTA (Genera la URL/ruta como string):
// import Torta from './torta.svg';

// IMPORTACIÓN CORRECTA (Usa la exportación nombrada ReactComponent y le asigna el alias Torta).
// NOTA: Se ha corregido la ruta. Asegúrate de que esta ruta (../assets/torta.svg) sea correcta respecto a tu archivo torta.svg real.
import { ReactComponent as Torta } from '../assets/torta.svg';

const TortaComponente = () => {
return (
<div className="flex flex-col items-center justify-center p-8 bg-white rounded-xl shadow-lg m-4">
<h1 className="text-3xl font-bold text-gray-800 mb-4">¡Feliz Día!</h1>
{/* AQUÍ SE USA EL COMPONENTE:
Ahora <Torta /> es una función de React, no una cadena de texto.
Le podemos pasar props como className, fill, width, etc.
*/}
<Torta
className="transition-transform duration-300 hover:scale-110"
width={150}
height={150}
fill="#ff9a8d" // Un color de pastel bonito
/>

<p className="mt-4 text-gray-600">Este SVG ahora se comporta como un componente React nativo.</p>
</div>
);
};

export default TortaComponente;

Resumen de la Corrección

Asegúrate de que tu línea de importación se vea así:

JavaScript
import { ReactComponent as NombreDeseado } from './ruta/al/archivo.svg';

Todavía no entiendo qué estoy haciendo exactamente al transformar un SVG en un componente de React.

Entiendo perfectamente tu confusión. Es uno de los conceptos más difíciles de entender cuando se empieza a trabajar con React y herramientas de bundling como Vite o Webpack, especialmente en cómo manejan los archivos que no son JavaScript (como los SVG).

La clave está en que el sistema de importación moderno (import ... from '...') tiene múltiples propósitos.

Aquí te explico la diferencia fundamental entre importar un SVG como URL y como componente, que es la función de SVGR.

Voy a generar un archivo Markdown con la explicación.

Explicación: SVG como Componente React

El Misterio de la Doble Importación de SVG

Cuando importas un archivo en un proyecto de React moderno, el bundler (Vite, en este caso) lo procesa según su tipo. Para un SVG, el bundler ofrece dos "sabores" de importación, y SVGR es el responsable de crear el segundo.

1. La Importación por Defecto (El Error que Tuviste)

Cuando escribes:

import Torta from './torta.svg';
// Torta === "[http://127.0.0.1:5173/resources/images/torta.svg](http://127.0.0.1:5173/resources/images/torta.svg)"

¿Qué pasa? El bundler interpreta el SVG como un activo estático (una imagen o archivo de recursos). Su valor por defecto es la URL pública donde se encontrará ese archivo en el navegador.

¿Por qué falla? React ve la importación Torta, cuyo valor es una cadena de texto (ej. "http://..."), y asume que quieres crear un elemento HTML con ese nombre de etiqueta: <http://.../>. Como la URL no es un nombre de etiqueta HTML válido (<div>, <span>, etc.), lanza el error InvalidCharacterError.

Uso Correcto de la URL: Este método solo sirve para usar el SVG como una fuente de imagen tradicional:

<img src={Torta} alt="Una torta" /> 
// o en CSS: background-image: url(${Torta})

2. La Importación Nombrada ReactComponent (La Solución)

Aquí es donde interviene SVGR. SVGR es un cargador (loader) que, antes de que el bundler lo convierta en una URL, lo lee y hace lo siguiente:

  1. Transformación a JSX: Convierte el código XML del SVG en una estructura de función que devuelve JSX.

  2. Exportación Nombrada: Exporta esta función de componente bajo el nombre ReactComponent.

Cuando escribes:

import { ReactComponent as Torta } from './torta.svg';
// Torta === función (props) => { return <svg>...</svg> }

¿Qué pasa? Al usar import { ReactComponent as Torta }, estás diciendo: "No quiero la URL por defecto. Quiero la función componente que generó SVGR, y la llamaré Torta."

¿Por qué funciona? Ahora, Torta es una función válida de React. Cuando la usas en JSX como <Torta />, React la invoca, renderiza el código SVG directamente en el DOM y, lo más importante, puedes controlar sus propiedades (props).

Beneficios de usar SVG como Componente

Característica

Importación como URL (<img>)

Importación como Componente (<Torta />)

Control de Estilo

Limitado. Solo width, height.

Total. Puedes pasar className, fill, stroke para cambiar colores o animaciones con CSS.

Interactividad

Ninguna. Es una imagen estática.

Total. Puedes agregar onClick a partes del SVG, manejar eventos del mouse, etc.

Rendimiento

Se carga como un recurso externo (petición HTTP).

Se inyecta directamente en el DOM (código en línea). Más rápido y evita peticiones adicionales.

Espero que esta explicación aclare por qué necesitas usar esa sintaxis de importación específica (import { ReactComponent as Torta } from '...') cuando quieres que tu SVG se comporte como un elemento nativo y manipulable dentro de tu aplicación React.


No hay comentarios: