Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic SVG imports? #72

Open
wmonecke opened this issue Mar 3, 2023 · 3 comments
Open

Dynamic SVG imports? #72

wmonecke opened this issue Mar 3, 2023 · 3 comments

Comments

@wmonecke
Copy link

wmonecke commented Mar 3, 2023

Is there a way to import svgs dynamically?

I would love to be able to do something like this:

dynamic import hook

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

Note: If I pass SvgIcon to the src of an img tag it renders the icon properly so it is being imported.

icon.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}
    />
  );
};

This is currently not working.

How can I convert the imported file into a component?

    const imported = await import(`../../assets/icons/${name}.svg`).then(
          module => module.default,
        );
@flydev-fr
Copy link

@wmonecke you could take a look on this example on stackblitz and answer on stackoverflow to check if it fit your needs.

@pd4d10
Copy link
Owner

pd4d10 commented May 3, 2023

Would Vite glob import help?

@GideonMax
Copy link

aren't you supposed to import with ?react
for example:
import Logo from "./logo.svg?react"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants