Open wmonecke opened 1 year ago
Would Vite glob import help?
aren't you supposed to import with ?react for example: import Logo from "./logo.svg?react"
有没有办法动态导入 svgs?
我很想能够做这样的事情:
动态导入钩子
import { FunctionComponent } from 'preact'; import { useEffect, useRef, useState } from 'preact/hooks'; type Props = { name: string; }; export const useDynamicSVGImport = ({ name }: Props) => { const ImportedIconRef = useRef< FunctionComponent<SVGSVGElement> | undefined >(); const [loading, setLoading] = useState(false); const [error, setError] = useState<Error>(); useEffect(() => { setLoading(true); const importIcon = async (): Promise<void> => { try { const imported = await import(`../../assets/icons/${name}.svg`).then( module => module.default, ); // logs: /src/assets/icons/spinner.svg if I pass name = spinner console.log('imported', imported); ImportedIconRef.current = imported; } catch (err) { console.log(err); setError(err); } finally { setLoading(false); } }; importIcon(); }, [name]); return { loading, error, SvgIcon: ImportedIconRef.current, }; };
注意:如果我传递
SvgIcon
给src
标签,img
它会正确呈现图标,以便被导入。图标.tsx
import { FunctionComponent } from 'preact'; import { useDynamicSVGImport } from '~/hooks/icons/use-dynamic-import'; type Props = { name: string; className?: string; isOutlineIcon?: boolean; }; export const Icon: FunctionComponent<Props> = ({ name, className, isOutlineIcon = false, ...restProps }) => { const { error, loading, SvgIcon } = useDynamicSVGImport({ name }); if (error || !SvgIcon || loading) { return null; } return ( <SvgIcon className={` fill-slate-400 ${isOutlineIcon ? '' : 'fill-current'} ${className ? className : 'h-5 w-5 text-lightBlack'}`} {...restProps} /> ); };
目前这不起作用。
如何将导入的文件转换为组件?
const imported = await import(`../../assets/icons/${name}.svg`).then( module => module.default, );
Need to downgrade the plugin to version 2.x, the latest 4.x version doesn't work with dynamic introduction
You need to add '?react' to import path like:
const imported = await import(
../../assets/icons/${name}.svg?react).then( module => module.default, );
If you're using Typescript; Make sure you have this line in vite-env.d.ts:
/// <reference types="vite-plugin-svgr/client" />
my solution
// dynamic.tsx
import React from 'react';
const Dynamic: React.FC<React.SVGAttributes<SVGSVGElement> & {icon: string}> = (props) => {
const {icon, ...svgProps} = props;
if(icon.length === 0) return (<></>);
const Icon = React.lazy(async () => {
let component = await import(`./assets/non_data.svg?react`);
try {
component = await import(`./assets/${icon}.svg?react`);
} catch (_) { /* empty */ }
return component;
});
return (
<React.Suspense>
<Icon { ...svgProps } />
</React.Suspense>
);
}
export default Dynamic;
// App.tsx
import Dynamic from './dynamic'
function App() {
return (
<span style={{ color: 'blue' }}><Dynamic icon="power" fill="currentColor" /></span>
}
export default App
Is there a way to import svgs dynamically?
I would love to be able to do something like this:
dynamic import hook
Note: If I pass
SvgIcon
to thesrc
of animg
tag it renders the icon properly so it is being imported.icon.tsx
This is currently not working.
How can I convert the imported file into a component?