reactjs - Jest & react-router-dom: React.createElement: type is invalid - 期望一个字符串(用于内置组件)......但得到:未定义
问题描述
我正在为一个组件编写测试,该组件Link
来自react-router-dom
.
组件本身可以正常工作而不会给出任何错误或警告。
但是,当使用shallow
from呈现组件时enzyme
,它会在控制台中显示以下错误消息。
警告:React.createElement:类型无效——需要一个字符串(对于内置组件)或一个类/函数(对于复合组件),但得到:未定义。
您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。
据我研究,当您错误地导入 React 模块(或组件)时,显然会发生此错误。
例如
import Link from 'react-router-dom'; // Wrong!
import { Link } from 'react-router-dom'; // Correct!
但是,在我的情况下,Link
它是正确导入的,但它仍然给出上面的警告消息。
这是该组件的一个片段。
import React from 'react';
import { Link, useHistory } from 'react-router-dom';
// other modules here
const ListItem = (props) => {
const history = useHistory();
const queryParameter = _.get(history, 'location.search', '');
const pathName = `/blah/${props.id}${queryParameter}`;
return (
<li>
<Link to={pathName}>
<div>blah blah...</div>
</Link>
</li>
);
};
(当我注释掉时<Link>
,警告消息将从控制台消失。所以,使用useHistory()
应该与警告无关)
jest.mock('react-router-dom', () => ({
useHistory: jest.fn()
}));
describe('ListItem', () => {
const baseProps = { /* initial props here*/ };
it("renders the name", () => {
const wrapper = shallow(<ListItem {...baseProps} />);
// the line above shows the warning message in the console
});
});
我完全一无所知。任何建议将被认真考虑。
解决方案
听起来您没有导入正确的文件(如果您有一个.(s)css
或test.js
文件与组件共享相同的名称并位于同一根目录中,那么 webpack 可能会将错误的文件导入到测试文件中——因此,我建议指定组件名称和扩展名:index.js
或ListItem.js
)。否则,您可能会忘记导出ListItem
组件。
工作示例(此示例使用mount
和Router
-- 单击Test
选项卡以运行测试):
组件/ListItem/index.js
import React from "react";
import get from "lodash/get";
import { Link, useHistory } from "react-router-dom";
function ListItem({ children, id, destination }) {
const history = useHistory();
const query = get(history, ["location", "search"]);
return (
<li style={{ margin: 0, padding: 0 }}>
<Link to={`${destination}/${id}${query}`}>
<div>{children}</div>
</Link>
</li>
);
}
export default ListItem;
组件/ListItem/__tests__/ListItem.test.js
import React from "react";
import { mount } from "enzyme";
import { Router } from "react-router-dom";
import { createMemoryHistory } from "history";
import ListItem from "../index.js";
const children = "Test";
const id = 1;
const destination = "/home";
const query = "?id=1";
const initialPath = `${destination}/${id}${query}`;
const history = createMemoryHistory({
initialEntries: [initialPath]
});
const initProps = {
children,
id,
destination
};
const wrapper = mount(
<Router history={history}>
<ListItem {...initProps} />
</Router>
);
describe("ListItem", () => {
afterAll(() => {
wrapper.unmount();
});
it("renders the children", () => {
expect(wrapper.find("div").text()).toEqual(children);
});
it("renders a Link that contains destination, params.id and query", () => {
expect(wrapper.find("Link").props().to).toEqual(
`${destination}/${id}${query}`
);
});
});
推荐阅读
- flutter - 导航弹出后Flutter获取参考
- google-apps-script - 如何使用脚本编辑器在单元格中添加今天的日期加上 7 天
- node.js - 为什么请求超时时不抛出错误?
- awk - 通过搜索前缀提取整个单词
- r - 错误使用 gam 模型分析浮游植物丰度和环境参数(mgcv 包)
- jquery - 由于某种原因无法使用更改方法的无线电输入
- c# - MPRemoteCommandCenter 播放/暂停命令未正确更新
- python - Python - 如何从 .csv 文件读取到字典?
- reactjs - 无法对未安装的组件执行 React 状态更新。我试过 AbortController,但它在异步功能完成之前中止
- javascript - 为什么使用 'new Date()' 以及如何在小于 10 的数字前面获得 0 ?- 数字时钟Javascript