Tengo una función que toma algunos argumentos y genera un SVG. Quiero importar dinámicamente ese svg según el nombre pasado a la función. Se parece a esto:
import React from 'react'; export default async ({name, size = 16, color = '#000'}) => { const Icon = await import(/* webpackMode: "eager" */ `./icons/${name}.svg`); return <Icon width={size} height={size} fill={color} />; };De acuerdo con la documentación del paquete web para importaciones dinámicas y el comentario mágico "ansioso":
"No genera ningún fragmento adicional. Todos los módulos se incluyen en el fragmento actual y no se realizan solicitudes de red adicionales. Aún se devuelve una Promesa pero ya está resuelta. A diferencia de una importación estática, el módulo no se ejecuta hasta que se llama a importar () está hecho."
Esto es a lo que se resuelve mi icono:
> Module default: "static/media/antenna.11b95602.svg" __esModule: true Symbol(Symbol.toStringTag): "Module"Intentar representarlo de la forma en que mi función está tratando de hacerlo me da este error:
Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
No entiendo cómo usar este Módulo importado para representarlo como un componente, ¿o es posible de esta manera?
Sus funciones de representación (para componentes de clase) y componentes de función no deben ser asíncronos (porque deben devolver DOMNode o nulo; en su caso, devuelven una Promesa). En su lugar, puede renderizarlos de la forma habitual, después de eso, importe el icono y utilícelo en el siguiente renderizado. Prueba lo siguiente:
const Test = () => { let [icon, setIcon] = useState(''); useEffect(async () => { let importedIcon = await import('your_path'); setIcon(importedIcon.default); }, []); return <img alt='' src={ icon }/>; };Hice un cambio basado en la respuesta https://github.com/facebook/create-react-app/issues/5276#issuecomment-665628393
export const Icon: FC<IconProps> = ({ name, ...rest }): JSX.Element | null => { const ImportedIconRef = useRef<FC<SVGProps<SVGSVGElement>> | any>(); const [loading, setLoading] = React.useState(false); useEffect((): void => { setLoading(true); const importIcon = async (): Promise<void> => { try { // Changing this line works fine to me ImportedIconRef.current = (await import(`!!@svgr/webpack?-svgo,+titleProp,+ref!./${name}.svg`)).default; } catch (err) { throw err; } finally { setLoading(false); } }; importIcon(); }, [name]); if (!loading && ImportedIconRef.current) { const { current: ImportedIcon } = ImportedIconRef; return <ImportedIcon {...rest} />; } return null; };Una solución para cargar el svg dinámicamente podría ser cargarlo dentro de un img usando require , por ejemplo:
<img src={require(`../assets/${logoNameVariable}`)?.default} />