Jest加载SVG失败致React组件类型无效问题求助
问题描述
在React+TypeScript项目中运行Jest测试时出现警告:
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined。
经排查问题源于Jest无法加载SVG文件,已安装jest-transformer-svg模块并配置Jest规则,但错误仍未消除。
错误详情
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. Check the render method of `TagInput`. at TagInput (/Users/newin/Desktop/homeCoding/deopjibhoeui/src/components/Input/TagInput.tsx:14:3) 34 | onClick={() => removeTags(index)} 35 | > > 36 | <RemoveIcon /> | ^ 37 | </span> 38 | </li> 39 | ))}
涉及代码
TagInput组件代码
import React from 'react'; import styles from './TagInput.css'; import { ReactComponent as RemoveIcon } from '../../assets/svg/RemoveIcon.svg'; import { InputTag } from '../../core/hooks/types/useTagInput'; export interface TagInputProps { tags: InputTag[]; addTags: (event: React.KeyboardEvent<HTMLInputElement>) => void; removeTags: (index: number) => void; placeholder?: string; } const TagInput = ({ tags, addTags, removeTags, placeholder }: TagInputProps) => { return ( <div className={styles}> <div className="tags-input"> <input className="tags-input-field" type="text" onKeyUp={(event) => (event.key === 'Enter' ? addTags(event) : null)} placeholder={placeholder} /> <ul id="tags"> {tags.map((tag, index) => ( <li key={index} className="tag"> <span className="tag-title">{tag}</span> <span className="tag-close-icon" onClick={() => removeTags(index)} > <RemoveIcon /> </span> </li> ))} </ul> </div> </div> ); }; export default TagInput;
Jest配置(jest-config.json)
{ "preset": "ts-jest", "testEnvironment": "jsdom", "setupFilesAfterEnv": ["<rootDir>/src/setupTests.ts"], "moduleNameMapper": { "^.+\\.svg$": "jest-transformer-svg" }, "transform": { "^.+\\.svg$": "jest-transformer-svg", "^.+\\.(ts|tsx)?$": "ts-jest", "^.+\\.(js|jsx)$": "babel-jest", "^.+\\.css$": ["jest-transform-css", { "modules": true }] } }
package.json中的devDependencies
"devDependencies": { "@babel/core": "^7.24.9", "@babel/preset-env": "^7.25.3", "@babel/preset-typescript": "^7.24.7", "babel-jest": "27.5.1", "jest": "27.5.1", "jest-environment-jsdom": "27.5.1", "jest-svg-transformer": "^1.0.0", "jest-transform-css": "^6.0.1", "jest-transformer-svg": "^2.0.2", "ts-jest": "^27.1.4" }
执行yarn install后运行yarn test即可触发错误。
解决方法
问题核心是jest-transformer-svg默认仅支持SVG的默认导入,无法匹配你代码中{ ReactComponent as RemoveIcon }的命名导入方式,导致Jest解析后拿到undefined。
方案1:自定义SVG Mock文件(推荐)
- 在项目根目录创建
__mocks__/svgMock.tsx文件,内容如下:
import React from 'react'; const MockSVG = ({ children, ...props }: React.SVGProps<SVGSVGElement>) => ( <svg {...props}>{children}</svg> ); // 支持命名导出的ReactComponent export const ReactComponent = MockSVG; // 同时支持默认导入 export default MockSVG;
- 修改Jest配置(jest-config.json):
- 将
moduleNameMapper中的SVG映射指向自定义mock文件 - 移除
transform中针对SVG的配置项
修改后的配置片段:
- 将
"moduleNameMapper": { "^.+\\.svg$": "<rootDir>/__mocks__/svgMock.tsx" }, "transform": { "^.+\\.(ts|tsx)?$": "ts-jest", "^.+\\.(js|jsx)$": "babel-jest", "^.+\\.css$": ["jest-transform-css", { "modules": true }] }
方案2:调整SVG导入方式
如果不想新增mock文件,可以把代码中的SVG导入改为默认导入:
// 替换原命名导入 import RemoveIcon from '../../assets/svg/RemoveIcon.svg';
这种方式无需修改Jest配置,但需要调整所有使用SVG组件的导入代码,适合小型项目。
方案3:升级Jest依赖(可选)
当前使用的Jest 27.x版本较老旧,升级到29.x版本配合最新的jest-transformer-svg可能解决兼容性问题,但升级可能需要同步调整其他配置(如babel、ts-jest版本),需谨慎操作。
内容的提问来源于stack exchange,提问作者Blue A
相关产品推荐
相关产品推荐

