“ReactSVG”不能用作 JSX 组件

问题描述 投票:0回答:1

我正在开始我的第一个 React/Next.js 项目,我需要导入一个 SVG 文件并在渲染之前对其进行修改。 我试图找到一些可以让我做到这一点的模块,然后我选择了react-svg https://github.com/tanem/react-svg/ 在开发过程中,一切都按需要进行。 当我试图抑制来自 ESLINT 尝试部署的警告和错误时,问题就出现了。

我像这样使用ReactSVG:

'use client'

import { ReactSVG } from "react-svg";

...

const Page = () => {

...

const attachTurnsToSvg = (elements = []) => {
 elements.forEach((element: SVGRectElement) => {
  //insert text inside SVGelements
 });
};

    const attachCallsToSvg = (elements = []) => {
        elements.forEach((element: SVGCircleElement) => {
            element.addEventListener('click', (e) => {
                console.debug('clicked', e);
            });
        });
    };

return(
<>
...
                <ReactSVG
                    src="/mysvg.svg" 
                    beforeInjection={(svg) => {
                        const svgWidth = (width !== undefined ? 0.625 * width : 1200);
                        const svgHeight = (height !== undefined ? 0.88 * height : 800);
                        svg.setAttribute('style', `width: ${svgWidth}px; height: ${svgHeight}px;`);
                      }}
                    afterInjection={(svg: { querySelectorAll: (arg0: string) => never[]; }) => {
                        const rects = svg?.querySelectorAll('rect.turnRect') || [];
                        attachTurnsToSvg(rects);
                        const circles = svg?.querySelectorAll('circle.callCircle') || [];
                        attachCallsToSvg(circles);
                    }}
                    className={styles.map} 
                />
</>)
}

export default Page;

开发中一切似乎都工作正常,但是我收到了错误: “JSX 元素类不支持属性,因为它没有 'props' 属性。”, “ReactSVG”不能用作 JSX 组件。 其类型“typeof ReactSVG”不是有效的 JSX 元素类型。 类型“typeof ReactSVG”不可分配给类型“new (props:any, deprecatedLegacyContext?:any) => Component”。 类型“ReactSVG”缺少类型“Component”中的以下属性:context、setState、forceUpdate、props、refs

并且无法构建应用程序。

其他一切都按我的预期工作,但我似乎找不到其他解决方案来使其工作......

reactjs svg next.js
1个回答
0
投票

我建议定义您自己的 SVG 组件,因为这将使将来的自定义变得更加容易。从 SVG 中提取内容(如果可能,将重复元素转换为地图循环)。

例如:

const circles = [{ cy: 20, cx: 20, fill: "red", ... }, ...]
const rects = [{ y: 0, x: 0, textToInsert: "Hello", ... }, ...]

export default function MySVG() {
   return <svg width={1200} height={800}>
      {circles.map(circleProps => <circle {...circleProps} className="callCircle" onClick={(e) => console.log("clicked", e)} />)}
      {rect.map(({ textToInsert, ...rectProps }) => <>
         <rect {...rectProps} className="turnRect" onClick={(e) => console.log("clicked", e)} />
         { /* You cannot insert a SVG text inside a rect, but you can overlay it */ }
         <text x={rectProps.x} y={rectProps.y}>{textToInsert}</text>
      </>)}
   <svg/>
}
import MySVG from "./MySVG.tsx";

const Page = () => {
   return <MySVG />;
}

export default Page;

对于您的用例来说,这可能不是一个理想的解决方案,但这种方法将允许您对 SVG 进行更多自定义,同时具有更多“React-y”方法,而不是使用在初始渲染后计算的本机 JS 查询选择器。

但是,如果您需要修改用例中预先存在的 SVG,则可以在

useEffect
中使用本机 JS 来完成此操作。例如:

import { useEffect, useRef } from 'react';
import MySvg from "/mysvg.svg"; // use SVGR or babel-plugin-inline-react-svg to directly render an inline SVG

export default function Page() {
   const svgRef = useRef(null);

   useEffect(() => {
     if (svgRef.current) {
        const rects = svg?.querySelectorAll('rect.turnRect') || [];
        // do stuff with rects
        const circles = svg?.querySelectorAll('circle.callCircle') || [];
        // do stuff with circles
     }
   }, [svgRef.current])

   return <MySvg height={800} width={1200} />
}

您可以在线找到教程,将 SVGR 或类似的 SVG 解析器设置到您的 NextJS 项目中。

我希望这有帮助。请随时发表评论以提出进一步的问题:)!

© www.soinside.com 2019 - 2024. All rights reserved.