かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Vite React (TypeScript) で SVG を ReactComponent として扱いたい

create-react-app で作成した React のプロジェクトでは SVG ファイルを ReactComponent としてインポートすると inline-svg (<svg></svg>) として出力できるので path に CSS を当てたい場合などに便利です。

今回 Vite で作成した React (TypeScript) のプロジェクトで同じことをしようとしたのですがデフォルトの状態では SVGReactComponent として import できませんでした。

vite-plugin-svgr を使う

内部的に svgr という SVG を ReactComponent に変換できるツールを使っている vite-plugin-svgr プラグインがあったのでこちらを使うことにしました

Then SVG files can be imported as React components, just like create-react-app does
cf. vite-plugin-svgr - npm

vite.config.tsプラグインを追加すれば import { ReactComponent as Logo } from './logo.svg' の形で SVG React 内で扱えるようになります

$ npm i -D vite-plugin-svgr

vite.config.ts

import svgr from 'vite-plugin-svgr'

export default {
  // ...
  plugins: [svgr()],
}

SVG のインポート文で TypeScript のエラーが出る

SVG を ReactComponent としてインポートしている箇所で次のような TypeScript のエラーが表示されていました。(ビルドはされていたので警告かも)

// App.tsx
import { ReactComponent as Logo } from './logo.svg';

=> Module '"*.svg"' has no exported member 'ReactComponent'. Did you mean to use 'import ReactComponent from "*.svg"' instead?

SVG ファイルは ReactComponent として export されてないトノコト。
それはそう。

.svg ファイルは ReactComponent として export さている体の型を宣言してしまえば OK

適当な .d ファイルを作成して型定義する

svg.d.ts

declare module '*.svg' {
  import React = require('react');
  export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
}

cf. reactjs - Module '"*.svg"' has no exported member 'ReactComponent' - Stack Overflow

これで import { ReactComponent as ComponentName } from './path/to/svgFile.svg' の型エラーが解消され JSX 内でコンポーネントとして扱えるようになりました!!

// App.tsx
import { ReactComponent as Logo } from './logo.svg';

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

₍ ᐢ. ̫ .ᐢ ₎ できた!


[参考]