React引入SVG文件报相邻JSX元素需包裹闭合标签错误
React + Chakra UI 引入多根节点SVG编译报错解决方案
问题复现
- 技术栈:React + Chakra UI
- 编译报错信息:
Compiled with problems:X ERROR [eslint] src/svg/banner.jsx Line 15:2: Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? (15:2)
- 异常SVG特征:代码包含2个并列的根级
<svg>标签,无统一父容器 - 已尝试无效的引入方式:
- 作为React组件引入:
import { ReactComponent as Logo } from "../svg/banner.svg"; - 作为静态资源引入:
import banner from "../svg/banner.svg";
- 作为React组件引入:
报错原因
JSX语法强制要求单个组件只能返回一个根节点,直接将两个并列的SVG标签放在JSX文件中解析时,会违反单根节点规则触发ESLint解析错误。同时原生SVG文件规范和构建工具的SVG解析loader均不支持多根节点的SVG文件直接被解析为React组件或可正常加载的静态资源。
可行解决方案
方案1:用React Fragment包裹并列SVG(最快适配已写好的JSX格式SVG)
如果已经把SVG代码放在.jsx后缀的文件中,直接用React Fragment(空标签)把两个并列的SVG标签包裹即可,不需要引入额外依赖:
// src/svg/banner.jsx const BannerSvg = () => { return ( <> <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <circle cx="50" cy="50" r="40" stroke="blue" fill="lightblue" /> </svg> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1921.641" height="170.5" viewBox="0 0 1921.641 170.5" > <defs> <linearGradient id="linear-gradient" x1="-0.038" y1="-1.902" x2="1.1" y2="2.41" gradientUnits="objectBoundingBox" > <stop offset="0" stop-color="#4040be" /> <stop offset="0.36" stop-color="#4e67eb" /> <stop offset="1" stop-color="#31c3ac" /> </linearGradient> </defs> <path id="Path_30" data-name="Path 30" d="M0,0H1921.641V170.5H0Z" opacity="0.8" fill="url(#linear-gradient)" /> </svg> </> ) } export default BannerSvg;
使用时直接引入组件渲染即可:
import BannerSvg from "../svg/banner.jsx"; // 组件内调用 <BannerSvg />
注意:如果页面中存在其他SVG,建议修改当前SVG内的渐变id值,避免id重名导致样式冲突。
方案2:合并为单根节点SVG(保留.svg文件格式)
如果需要保留文件为.svg后缀,使用ReactComponent或静态资源方式引入,可新增一个根级SVG标签,将两个原有SVG作为子节点放入,根据布局需求调整子SVG的坐标和整体视口大小即可:
<!-- banner.svg --> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1921.641 270.5" > <!-- 圆形SVG,可根据实际布局需求调整x/y坐标 --> <svg width="100" height="100" y="170.5"> <circle cx="50" cy="50" r="40" stroke="blue" fill="lightblue" /> </svg> <!-- 渐变背景SVG --> <svg width="1921.641" height="170.5" viewBox="0 0 1921.641 170.5" > <defs> <linearGradient id="banner-linear-gradient" x1="-0.038" y1="-1.902" x2="1.1" y2="2.41" gradientUnits="objectBoundingBox" > <stop offset="0" stop-color="#4040be" /> <stop offset="0.36" stop-color="#4e67eb" /> <stop offset="1" stop-color="#31c3ac" /> </linearGradient> </defs> <path id="Path_30" data-name="Path 30" d="M0,0H1921.641V170.5H0Z" opacity="0.8" fill="url(#banner-linear-gradient)" /> </svg> </svg>
处理完成后即可正常使用两种原有引入方式:
- 组件方式引入:
import { ReactComponent as BannerLogo } from "../svg/banner.svg";直接渲染<BannerLogo /> - 静态资源方式引入:
import banner from "../svg/banner.svg";通过img标签或Chakra UI的Image组件渲染
方案3:适配Chakra UI组件渲染
合并为单根SVG后,可直接使用Chakra UI内置的Image组件渲染静态资源引入的SVG,方便快速配置样式:
import { Image } from '@chakra-ui/react' import banner from "../svg/banner.svg"; <Image src={banner} alt="page banner" w="100%" objectFit="cover" />
内容的提问来源于stack exchange,提问作者Rogestav
相关产品推荐
相关产品推荐

