简体   繁体   English

Jest & react-router-dom: React.createElement: type is invalid - 期望一个字符串(用于内置组件)......但得到:未定义

[英]Jest & react-router-dom: React.createElement: type is invalid -- expected a string (for built-in components) ... but got: undefined

I'm writing tests for a component that has Link from react-router-dom .我正在为具有来自react-router-dom Link的组件编写测试。

The component itself works without giving any error or warning.组件本身可以正常工作而不会给出任何错误或警告。

However, when the component is rendered with shallow from enzyme , it shows the following error message in the console.但是,当组件使用来自enzymeshallow渲染时,它会在控制台中显示以下错误消息。

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined.警告:React.createElement:类型无效——需要一个字符串(对于内置组件)或一个类/函数(对于复合组件),但得到:未定义。

You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。

As far as I've researched, apparently this error occurs when you wrongly import a React module (or a component).据我研究,当您错误地导入 React 模块(或组件)时,显然会发生此错误。

eg例如

import Link from 'react-router-dom'; // Wrong!
import { Link } from 'react-router-dom'; // Correct!

However, in my case, Link is correctly imported but it still gives the warning message above.但是,在我的情况下, Link已正确导入,但仍会给出上述警告消息。

Here's a snippet of the component.这是该组件的一个片段。

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>
  );
};

(When I comment-out <Link> , the warning message will be gone from the console. So, using useHistory() should have nothing to do with the warning) (当我注释掉<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
  });
});

I'm completely clueless.我完全一无所知。 Any advice will be appreciated.任何建议将被认真考虑。

I ran into this issue as well today, and this is the only place I've ever seen with anyone experiencing the same thing.我今天也遇到了这个问题,这是我见过的唯一一个遇到同样事情的人的地方。 After banging my head against the wall for an hour, I finally figured it out—and indeed, this is probably the cause of your issue as well.在我的头撞墙一个小时后,我终于弄明白了——事实上,这可能也是你问题的原因。 It's been 2 years since you asked this so you probably don't need the answer anymore, but for any future developers stumbling across this post...自从你问这个问题已经 2 年了,所以你可能不再需要答案了,但是对于任何未来的开发人员偶然发现这篇文章......

The component is importing correctly in practice but not in your tests because of your mock, specifically this part:由于您的模拟,该组件在实践中正确导入,但在您的测试中没有正确导入,特别是这部分:

jest.mock('react-router-dom', () => ({
  useHistory: jest.fn()
}));

This replaces all of the react-router-dom import with an object containing only the property useHistory , so importing Link from it gives you an undefined.这会将所有react-router-dom导入替换为仅包含属性useHistory的对象,因此从中导入Link会给您一个未定义的结果。 It's easily fixed as so:它很容易修复:

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useHistory: jest.fn()
}));

Sounds like you're not importing the correct file (if you have a .(s)css or test.js file that share the same name as the component and reside within the same root directory, then the wrong file may be imported by webpack into the test file -- as such, I'd recommend specifying the component name and extension: index.js or ListItem.js ).听起来您没有导入正确的文件(如果您有一个.(s)csstest.js文件与组件同名并位于同一根目录中,那么 webpack 可能会导入错误的文件进入测试文件——因此,我建议指定组件名称和扩展名: index.jsListItem.js )。 Otherwise, you likely forgot to export the ListItem component.否则,您可能忘记导出ListItem组件。

Working example (this example uses mount and Router -- click the Test tab to run the test):工作示例(此示例使用mountRouter ——单击Test选项卡运行测试):

编辑测试 RRD


components/ListItem/index.js组件/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;

components/ListItem/__tests__/ListItem.test.js组件/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}`
    );
  });
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 React.createElement:类型无效 - 预期是字符串(对于内置组件)或类/函数(对于复合组件)但得到:未定义 - React.createElement: type is invalid - expected a string (for built-in components) or a class/function (for composite components) but got: undefined React.createElement:类型无效 - 需要一个字符串(对于内置组件)或一个类/函数(对于复合组件)但未定义 - React.createElement: type is invalid — expected a string (for built-in components) or a class/function (for composite components) but got undefined React.createElement:type无效 - 期望一个字符串(对于内置组件) - React.createElement: type is invalid — expected a string (for built-in components) React.createElement:类型无效——需要一个字符串(对于内置组件)或一个类/函数(对于复合组件)但得到:null - React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: null React.createElement: 类型无效——需要一个字符串(对于内置组件)或一个类/函数(对于复合组件)但得到:对象 - React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object 警告:React.createElement:类型无效——需要一个字符串(对于内置组件)(React Webpack Phaser) - Warning: React.createElement: type is invalid -- expected a string (for built-in components) (React Webpack Phaser) React-一个文件应用程序-警告:React.createElement:类型无效-预期为字符串(对于内置组件) - React - one file app - Warning: React.createElement: type is invalid — expected a string (for built-in components) 警告:React.createElement:类型无效 - 需要一个字符串(对于内置组件)或一个类/函数(对于复合组件) - Warning: React.createElement: type is invalid — expected a string (for built-in components) or a class/function (for composite components) React.createElement:类型无效 - 需要一个字符串(对于内置组件)或一个类/函数(对于复合组件) - React.createElement: type is invalid — expected a string (for built-in components) or a class/function (for composite components) 警告:React.createElement:类型无效-预期为字符串(对于内置组件) - Warning: React.createElement: type is invalid — expected a string (for built-in components)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM