首页 > 解决方案 > 如何使用 create-react-app 从外部模块导入 svg react 组件?

问题描述

语境

为了使一些代码部分在许多反应项目中可重用,我有以下项目结构:

  1. @foo/design:包含设计内容,例如原始 svg 图像
  2. @foo/ui: 基于 Create React App for common 组件的 react 库
  3. @foo/project:使用的最终 CRA 项目foo/ui

图书馆

foo/ui库导出一些从以下位置导入 svg 图像的组件@foo/design

// MyComponent.ts
import React, { FC } from 'react';
import {
  ReactComponent as Logo,
} from '@foo/design/static/img/logo.svg';

export const MyComponent: FC = () => {
  return (
    <div>
      Some stuff.
      <Logo />
    </div>
  );
};

export default null;

该组件在相关的 Storybook 实例上完美运行,并使用如下@foo/ui方式编译:tsc

// MyComponent.js
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { ReactComponent as Logo, } from '@foo/design/static/img/logo.svg';
export var Navbar = function () {
    return (_jsxs("div", { children: ["Some stuff.", _jsx(Logo, {}, void 0)] }, void 0));
};
export default null;

这里也是相关tsconfig.json文件:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "declaration": true,
    "outDir": "./lib",
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react-jsx"
  },
  "include": ["src"],
  "exclude": [
    "src/samples",
    "src/**/*.stories.*",
    "src/**/*.test.*",
    "src/setupTests.js"
  ],
}

项目导入

在 上@foo/project,我添加了@foo/ui依赖项,@foo/design同时安装了包(需要@foo/ui)。

我以这种方式使用我的组件:

import { FC } from 'react';
import { MyComponent } from '@foo/ui'

const App: FC = () => {
  return (
    <MyComponent />
  );
}

export default App;

但这会产生以下错误:

Failed to compile.

./node_modules/@foo/ui/lib/MyComponent.js
Attempted import error: 'ReactComponent' is not exported from '@foo/design/static/img/logo.svg' (imported as 'Logo').

MyComponent.js但是,如果我直接在我的根应用程序组件上复制/粘贴 svg 导入行:

import { FC } from 'react';
import { ReactComponent as Logo, } from '@foo/design/static/img/logo.svg';

const App: FC = () => {
  return (
    <Logo />
  );
}

export default App;

这有效,svg 按预期显示。

这里也是 CRA 项目相关tsconfig.json文件:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

为什么ReactComponent从我的导入库中导入 CRA 后不起作用?解决这个问题的最简单方法是什么,@foo/ui只在内部使用?

谢谢

标签: javascriptreactjstypescriptsvgcreate-react-app

解决方案


我发现在类似情况下唯一的解决方法可以帮助我 - 内联定义 SVG 组件,使用https://svg2jsx.com/来准备组件。

因此,在您的情况下,您将无法使用共享 SVG 的 from@foo/design来创建包装器组件,但至少您将能够在@foo/ui.

花了很多时间,最近才解决它,所以无法解释根本问题是什么。


推荐阅读