运行单元测试时出现React.jsx: type is invalid错误
解决单元测试中自定义组件库导入的React类型无效警告
问题场景
从自定义维护的Storybook组件库导入Button、Modal等组件时,UI渲染完全正常,但运行基于React Testing Library + Webpack的单元测试时,测试虽能通过,控制台却抛出以下警告:
console.error Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. > 1 | import { Button, Modal } from 'components-library'; | ^
尝试改用默认导入import Button, Modal from 'components-library';无效,因为组件库未导出默认内容。组件库基于Material UI,其中Button的导出代码如下:
import { Button as MuiButton, ButtonProps as MuiButtonProps, } from '@mui/material'; export const Button = ({ children, ...rest }: ButtonProps) => { return ( <MuiButton variant='text'> {children} </MuiButton> ); };
其类型信息为:
(alias) const Button: ({ children, ...rest }: ButtonProps) => react_jsx_runtime.JSX.Element export Button
核心原因
这类问题基本是测试环境与开发/生产环境的模块解析策略不一致导致的:
- 测试Webpack配置可能强制将组件库按CommonJS模块解析,而组件库实际输出的是ES模块,导致导入的是整个模块对象而非组件本身
- 组件库的打包输出格式未适配测试环境的解析规则
解决方案
1. 调整测试Webpack的模块解析规则
在测试环境的Webpack配置中,优先读取组件库的ES模块入口:
module.exports = { // ...其他配置 resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'], mainFields: ['module', 'main'], // 先找module字段对应的ES模块文件 }, };
这会让Webpack优先加载组件库package.json中module字段指向的ES模块文件,而非main字段的CommonJS文件,避免解析偏差。
2. 确保组件库打包输出双格式
在组件库的package.json中同时声明ES模块和CommonJS入口,让不同环境按需选择:
{ "main": "dist/index.cjs.js", "module": "dist/index.esm.js", "types": "dist/index.d.ts" }
如果用Rollup或Vite打包组件库,配置同时输出两种格式即可。
3. 给组件库添加Webpack别名(临时方案)
如果前两种方法无效,可直接在测试Webpack配置中指定组件库的ES模块路径:
const path = require('path'); module.exports = { resolve: { alias: { 'components-library': path.resolve(__dirname, '../path/to/components-library/dist/index.esm.js'), }, }, };
4. 检查测试环境的Babel配置
若用Babel处理测试代码,确保@babel/preset-env不转换ES模块:
{ "presets": [ ["@babel/preset-env", { "modules": false }], // 保留ES模块结构,让Webpack处理 "@babel/preset-react", "@babel/preset-typescript" ] }
如果modules设为commonjs,Babel会把ES模块转成CommonJS,可能导致组件导入异常。
内容的提问来源于stack exchange,提问作者likava
相关产品推荐
相关产品推荐

