admin管理员组文章数量:1296338
I want to use svg as Component here are all steps that i did:
- HomeIcon is a svg icon that i want to use it but i get this error:
[ Server ] React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
How can i fix this?
my next.config.mjs:
import createNextIntlPlugin from "next-intl/plugin"; const withNextIntl = createNextIntlPlugin(); /** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config) => { // SVG // Grab the existing rule that handles SVG imports const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.(".svg") ); config.module.rules.push( // Reapply the existing rule, but only for svg imports ending in ?url { ...fileLoaderRule, test: /\.svg$/i, resourceQuery: /url/, // *.svg?url }, // Convert all other *.svg imports to React components { test: /\.svg$/i, issuer: fileLoaderRule.issuer, resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url use: [ { loader: "@svgr/webpack", options: { typescript: true, ext: "tsx", }, }, ], } ); // Modify the file loader rule to ignore *.svg, since we have it handled now. fileLoaderRule.exclude = /\.svg$/i; return config; }, }; export default withNextIntl(nextConfig);
I create svg.d.ts in my root directory:
declare module "*.svg" { import React from "react"; const SVG: React.VFC<React.SVGProps<SVGSVGElement>>; export default SVG; }
I added
svg.d.ts
inside tsconfig.json"include": [ "svg.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next.config.mjs" ],
In my Component :
import Navbar from "@/components/Navbar"; import { FC, ReactNode, SVGProps } from "react"; import HomeIcon from "@/assets/home.svg"; import Image from "next/image"; interface layoutProps { children: ReactNode; locale: string; } const Layout: FC<layoutProps> = ({ children, locale }) => { return ( <div> <Navbar locale={locale} /> {children} <div className="px-7 bg-white shadow-lg rounded-2xl fixed bottom-0 right-0 left- 0 border border-green-600 "> <div className="flex"> <div className="flex-1 group"> <a href="#" className="flex items-end justify-center text-center mx-auto px-4 pt-2 w-full text-gray-400 group-hover:text-green-800" > <span className="block px-1 pt-1 pb-1"> <HomeIcon className="w-6 h-6" /> <span className="block text-xs pb-2">Home</span> <span className="block w-5 mx-auto h-1 group-hover:bg-green-800 rounded-full"></span> </span> </a> </div> </div> </div> ); }; export default Layout;
I want to use svg as Component here are all steps that i did:
- HomeIcon is a svg icon that i want to use it but i get this error:
[ Server ] React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
How can i fix this?
my next.config.mjs:
import createNextIntlPlugin from "next-intl/plugin"; const withNextIntl = createNextIntlPlugin(); /** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config) => { // SVG // Grab the existing rule that handles SVG imports const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.(".svg") ); config.module.rules.push( // Reapply the existing rule, but only for svg imports ending in ?url { ...fileLoaderRule, test: /\.svg$/i, resourceQuery: /url/, // *.svg?url }, // Convert all other *.svg imports to React components { test: /\.svg$/i, issuer: fileLoaderRule.issuer, resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url use: [ { loader: "@svgr/webpack", options: { typescript: true, ext: "tsx", }, }, ], } ); // Modify the file loader rule to ignore *.svg, since we have it handled now. fileLoaderRule.exclude = /\.svg$/i; return config; }, }; export default withNextIntl(nextConfig);
I create svg.d.ts in my root directory:
declare module "*.svg" { import React from "react"; const SVG: React.VFC<React.SVGProps<SVGSVGElement>>; export default SVG; }
I added
svg.d.ts
inside tsconfig.json"include": [ "svg.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next.config.mjs" ],
In my Component :
import Navbar from "@/components/Navbar"; import { FC, ReactNode, SVGProps } from "react"; import HomeIcon from "@/assets/home.svg"; import Image from "next/image"; interface layoutProps { children: ReactNode; locale: string; } const Layout: FC<layoutProps> = ({ children, locale }) => { return ( <div> <Navbar locale={locale} /> {children} <div className="px-7 bg-white shadow-lg rounded-2xl fixed bottom-0 right-0 left- 0 border border-green-600 "> <div className="flex"> <div className="flex-1 group"> <a href="#" className="flex items-end justify-center text-center mx-auto px-4 pt-2 w-full text-gray-400 group-hover:text-green-800" > <span className="block px-1 pt-1 pb-1"> <HomeIcon className="w-6 h-6" /> <span className="block text-xs pb-2">Home</span> <span className="block w-5 mx-auto h-1 group-hover:bg-green-800 rounded-full"></span> </span> </a> </div> </div> </div> ); }; export default Layout;
- See stackoverflow/questions/65945886/… – Robert Longson Commented Feb 11 at 21:23
4 Answers
Reset to default 0You can't use SVG directly as a component. Instead, you can use it by using the Next.js Image component.
<Image
src={HomeIcon}
alt="Home Icon"
width={180}
height={38}
unoptimized={true}
/>
you can return svg in the component this way:
const Svg = () => (
<svg width="320" height="130" xmlns="http://www.w3./2000/svg">
<rect width="300" height="100" x="10" y="10" style="fill:rgb(0,0,255);stroke-width:3;stroke:red" />
</svg>
);
export default Svg;
in your next.config.mjs
., you can exclude SVG from the existing file loader rule.
// Exclude SVG from the existing file loader rule
if (fileLoaderRule) {
fileLoaderRule.exclude = /\.svg$/i;
}
full configuration here:
import createNextIntlPlugin from "next-intl/plugin";
const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config) => {
// Find the existing rule that handles SVG imports
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.(".svg")
);
// Exclude SVG from the existing file loader rule
if (fileLoaderRule) {
fileLoaderRule.exclude = /\.svg$/i;
}
// Add a new rule for SVGR
config.module.rules.push({
test: /\.svg$/i,
use: [
{
loader: "@svgr/webpack",
options: {
typescript: true,
},
},
],
});
return config;
},
};
export default withNextIntl(nextConfig);
or
fix the typescript error by importing SVGProps
and SVGSVGElement
as follows:
import { FC, SVGProps } from "react";
const Svg: FC<SVGProps<SVGSVGElement>> = () => (
<svg width="320" height="130" xmlns="http://www.w3./2000/svg">
<rect width="300" height="100" x="10" y="10" style="fill:rgb(0,0,255);stroke-width:3;stroke:red" />
</svg>
);
Either one should fix the issue.
If you want to use SVG as a React Component, first, you need to convert the SVG file into a React Component, you can use online tools like Svg2jsx
本文标签: reactjsHow to use SVG in NextjsStack Overflow
版权声明:本文标题:reactjs - How to use SVG in Next.js? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741635098a2389595.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论