提问人:Evry 提问时间:9/29/2021 更新时间:9/17/2022 访问量:2826
React/Typescript 无法将 svg 文件导入为组件
React/Typescript cannot import svg file as component
问:
在 React/Typescript/Webpack 5 项目中导入 svg 时出现此错误:
Cannot find module '../path' or its corresponding type declarations.
然后我补充道:
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement> & { title?: string }>;
const src: string;
export default src;
}
添加到文件中。如果我使用 svg 作为图像,它就可以工作。但是我需要将 svg 用作 ReactElement,因为我需要根据用户点击更改其内容。custom.d.ts
src
我试图将svg导入为。
import DislikeIcon from '../../media/icons/dislike.svg';
const Component = () => (<> <DislikeIcon /> </>)
然后我收到这个错误:
<data:image/svg... /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
然后我试了一下:
import { ReactComponent as DislikeIcon } from '../../media/icons/dislike.svg';
并得到:
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
我的webpack.config.js文件
module.exports = {
...
module: {
rules: [
{
test: /\.[jt]sx?$/,
use: ['babel-loader'],
exclude: /node_modules/,
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
},
{
test: /\.svg$/,
loader: 'url-loader',
},
{
test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
type: 'asset/resource',
},
{
test: /\.(woff(2)?|eot|ttf|otf)$/,
type: 'asset/inline',
},
],
},
...
};
我的 custom.d.ts 文件:
declare module '*.png' {
const value: string;
export = value;
}
declare module '*.jpg' {
const value: string;
export = value;
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement> & { title?: string }>;
const src: string;
export default src;
}
我的tsconfig.json文件:
{
"compilerOptions": {
"target": "ES5",
"module": "ESNext",
"moduleResolution": "node",
"lib": [
"DOM",
"ESNext"
],
"jsx": "react-jsx",
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowJs": true,
"checkJs": true,
},
"include": ["src/**/*", "./custom.d.ts"],
"exclude": ["node_modules", "build"],
}
我搜索了很多答案,但每个人都说了类似的话。这花了我一个我没有的时间。有人有什么建议吗?
感谢您的关注!
答:
我在这里找到了解决方案: https://duncanleung.com/typescript-module-declearation-svg-img-assets/ 感谢 (Duncan Leung) 解决方案是为媒体资产创建一个 ./src/@types/assets/index.d.ts TypeScript 模块声明文件。
关于 TypeScript 模块声明文件的一个主要问题是如何使用 typeRoots 属性将它们包含在 tsconfig.json 中。
属性 typeRoots 定义将包含类型声明的 types 文件夹,但 index.d.ts 模块声明文件必须位于子文件夹中,因为 typeRoots 下的每个子文件夹都被视为一个“包”并添加到项目中。
我们错误地尝试将.svg模块声明放在 ./src/@types/index.d.ts 下。
将.svg文件的 index.d.ts 移动到它自己的 ./src/@types/assets 子文件夹允许 TypeScript 正确识别.svg模块声明。
./src/@types/assets/index.d.ts
declare module "\*.svg" {
import React = require("react");
export const ReactComponent: React.SFC<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}
declare module "\*.jpg" {
const content: string;
export default content;
}
declare module "\*.png" {
const content: string;
export default content;
}
declare module "\*.json" {
const content: string;
export default content;
}
下面是一个示例 tsconfig.json:
tsconfig.json文件
{
"compileOnSave": false,
"compilerOptions": {
"target": "es5",
"module": "esnext",
"types": ["node"],
"moduleResolution": "node",
"esModuleInterop": true,
"typeRoots": ["./src/@types", "./node_modules/@types"],
"lib": ["dom", "es2015", "es2017"],
"jsx": "react",
"sourceMap": true,
"strict": true,
"resolveJsonModule": true,
"noUnusedLocals": true,
"noImplicitAny": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"baseUrl": "./",
"paths": {
"~/*": ["src/*"],
"@turn/styled": ["src/styled"]
}
},
"include": ["./src/**/*", "./test-utils/**/*", "./__mocks__/**/*"],
"exclude": ["node_modules"]
}
评论