reactjs - React/Typescript kan ikke importere SVG-fil som komponent
Jeg fik denne fejl, når jeg importerede svg i et React/Typescript/Webpack 5-projekt:
Cannot find module '../path' or its corresponding type declarations.
så tilføjede jeg:
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement> & { title?: string }>;
const src: string;
export default src;
}
til filen custom.d.ts. Det virker, hvis jeg bruger svg'en som et billede src. Men jeg har brug for at bruge svg'en som et ReactElement, fordi jeg har brug for at ændre dens indhold baseret på brugerklik.
Jeg prøvede at importere svg som
import DislikeIcon from '../../media/icons/dislike.svg';
const Component = () => (<> <DislikeIcon /> </>)
så fik jeg denne fejl:
<data:image/svg... /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.så prøvede jeg:
import { ReactComponent as DislikeIcon } from '../../media/icons/dislike.svg';
og fik:
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.Min webpack.config.js fil
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',
},
],
},
...
};
min custom.d.ts-fil:
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;
}
min tsconfig.json-fil:
{
"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"],
}
Jeg har søgt meget efter et svar, men alle siger noget lignende. Dette tager mig tid, jeg ikke har. Har nogen nogen forslag?
Tak for din opmærksomhed!
Svar #1
Jeg fandt løsningen på dette her: https://duncanleung.com/typescript-module-declearation-svg-img-assets/ Med tak til (Duncan Leung) Løsningen var at oprette en ./src/@types/assets/index.d.ts TypeScript moduldeklarationsfil for medieassets.
En hovedfælde ved TypeScript-moduldeklarationsfiler er, hvordan de inkluderes i tsconfig.json ved hjælp af typeRoots-egenskaben.
Egenskaben typeRoots definerer type-mappen, hvor typen erklæringer vil blive indeholdt, men index.d.ts moduldeklarationsfilerne skal være i en undermappe, da hver undermappe under typeRoots betragtes som en "pakke" og tilføjes til dit projekt.
Vi forsøgte fejlagtigt at placere .svg-moduldeklarationerne under ./src/@types/index.d.ts.
At flytte index.d.ts for .svg-filer til sin egen ./src/@types/assets-undermappe gjorde det muligt for TypeScript korrekt at genkende .svg-modulerklæringerne.
./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;
}
Her er et eksempel på 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"]
}
