React SVG导入为组件后无法渲染。

13

我在React JS中导入SVG文件时遇到了问题。

import { ReactComponent as Logo} from '../logo.svg'
我不知道为什么,在某些组件中<Logo />可以正确地呈现,而在其他组件中它并不显示。当我使用检查工具时,SVG图像确实存在且占据必要的空间,但SVG图像是空的。是否还有其他人遇到过这个问题?
6个回答

16

尝试:

import { default as logo } from '../logo.svg';

然后将其用作类型为img的节点中的源,就像这样:

<img src={logo} />

@GalShtengel 通常,导入静态资源会生成一个模块而不是React组件。Webpack使得将SVG作为React组件导入成为可能,但我不确定它的捆绑器和适当的配置。您可以查看:https://www.pluralsight.com/guides/how-to-load-svg-with-react-and-webpack - ljsb

4
我曾经遇到过完全相同的问题,将标志组件包裹在svg标签或div中,使其在屏幕上呈现。我也可以通过从Logo更改SVG颜色来进行设置。
import { ReactComponent as Logo} from '../logo.svg'

<svg><Logo fill="blue" width="100%" height="100%" /></svg>

// or...

<div><Logo fill="blue" width="100%" height="100%" /></div>

没有用<svg><div>标签包裹它,它会渲染一个空白图像,占据空间但没有任何视觉效果。一旦我加上了包装标签,它就正常工作了。我喜欢这种方法,因为您可以根据用户输入动态更改SVG样式。

2

我遇到了同样的问题,有时候是因为导入方式的问题,我通过以下方式解决:

import {ReactComponent as Icon} from 'pathtoyourfile.svg 然后使用: <Icon />

然而,有时候SVG文件会有相似的类名和ID名,如果你检查文件,你可能会看到clip0,image0,pattern0等。如果有多个SVG文件,它们的ID和Class名称很有可能会发生冲突并覆盖彼此。对我来说,最简单的解决方案是手动更改命名约定,不确定是否存在更自动化的解决方案?


感谢您的帮助,让我解决了问题!在多个SVG图像中使用相同的ID会导致浏览器混淆,无法正确渲染图像。您有任何想法为什么不同的SVG元素中存在相同的ID会互相覆盖吗? - Oleksandr Oliynyk

0

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community
1
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。-【来自审查】 - DevAddict

0
你可以这样做。
import React from 'react';
import logo from './logo.png'; // Tell webpack this JS file uses this image
console.log(logo); // /logo.84287d09.png
function Header() {
  // Import result is the URL of your image
  return <img src={logo} alt="Logo" />;
}
export default Header;

0
导入SVG图标文件非常简单,只需按照以下步骤操作即可。
  import { ReactComponent as YourSvg } from './logo.svg';

但是如果你使用Webpack 5和这个配置:
    {
    test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
    issuer: /\.[jt]sx?$/,
    use: ["babel-loader", "@svgr/webpack", "url-loader"],
    },

导入的SVG文件应该在运行时作为React组件可用。但是当你运行Webpack时,你会收到一个警告。无法从默认导出模块中导入名为'ReactComponent'(导入为'Logo')的命名导出项(只有默认导出项可用)。 我们可以通过Webpack 4中的file-loader来解决这个问题。我们似乎已经使用了一个Babel插件来支持它,但它不再起作用。所以我们有另一种选择。我们可以动态导入图标SVG,并且结果是,警告将消失。
interface IconProps extends React.SVGProps<SVGSVGElement> {
name: string;
size?: number;
className?: string;
onCompleted?: UseDynamicSVGImportOptions["onCompleted"];
}
const SVgComponent = ({
name,
size,
className, }: {
name: string;
className?: string;
size: number;
}) => {
function SvgIcon({ onCompleted }: PropsWithChildren<IconProps>) {
const { error, loading, SvgIcon } = useDynamicSVG(name, {
  onCompleted,
});

if (error) {
  return <>{error.message}</>;
}
if (loading) {
  return <>Loading...</>;
}
if (SvgIcon) {
  return (
    <>
      {className ? (
        <SvgIcon className={className} />
      ) : (
        <SvgIcon width={size} height={size} className={className} />
      )}
    </>
  );
}

return null;
}

const handleOnCompleted = useCallback(
(iconName: string) => console.log(`${iconName} successfully loaded`),
[]
);

return (
<div className="cartIcon-container">
  {/* <ShoppingIcon className="svg-icon" /> */}
  <SvgIcon
    name={name}
    onCompleted={handleOnCompleted}
    size={size}
    className={className}
  />
</div>
);
};

export default SVgComponent;

并且

export function useDynamicSVG(
name: any,
options: UseDynamicSVGImportOptions = {}
) {
const ImportedIconRef = useRef<React.FC<React.SVGProps<SVGSVGElement>>>();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error>();

 const { onCompleted, onError } = options;
useEffect(() => {
setLoading(true);
const importIcon = async (): Promise<void> => {
  try {
    const iconTypes = {
      cart: (await require(`../../assets/shopping.svg`)).ReactComponent,
      logo: (await require(`../../assets/logo_shop.svg`)).ReactComponent,
    };
    ImportedIconRef.current =
      "Cart" === name ? iconTypes.cart : iconTypes.logo;

    onCompleted?.(name, ImportedIconRef.current);
  } catch (err: any) {
    onError?.(err);
    setError(err);
  } finally {
    setLoading(false);
  }
};
importIcon();
}, [name, onCompleted, onError]);

return { error, loading, SvgIcon: ImportedIconRef.current };
}

最后,在您的组件内部添加它即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接