React.createElement: type is invalid - 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但是得到:对象

Posted

技术标签:

【中文标题】React.createElement: type is invalid - 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但是得到:对象【英文标题】:React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object 【发布时间】:2017-10-13 15:40:56 【问题描述】:

预期

我应该能够导出我的 App 组件文件并将其导入到我的 index.js 中。

结果

我收到以下错误

React.createElement: type is invalid -- 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但得到:对象


我的 index.js

const React = require('react');
const ReactDOM = require('react-dom');
const App = require('./components/App');
require('./index.css');

ReactDOM.render(
    <App />,
    document.getElementById('app')
);

然后在我的 components/App.js 中

const React = require('react');

export default class App extends React.Component 
    render() 
        return (
            <div>
                Hell World! Wasabi Sauce!
            </div>
        );
    


// module.exports = App;

如果我取消注释 module.exports = App; 它将起作用,但我正在尝试使用导出语法。让我发疯的是在另一个项目中,我在这里做同样的事情,而且工作正常:(

【问题讨论】:

请不要将 CommonJS 模块与 ES6 模块混用。 import/export 语法是为 ES6 模块保留的。使用 CommonJS 模块时,只需使用 module.exports 我不想混合它们,但由于某种原因,React 不喜欢我的 ES6 导出。在这个项目中,我在其他项目中使用它很好。 这可能取决于您的转译器/捆绑器处理 ES6 模块的方式。当路径错误时,'React.createElement: type is invalid' 错误很常见。你能不能 console.log(require('./components/App')) 看看导出了什么? 我知道Object __esModule: true, default: functiondefault.nameApp。我的路径是正确的,因为 commonJS 方式 module.exports 有效。 那么你应该使用const App = require('./components/App').default来获取组件(默认导出)。 【参考方案1】:

您遇到的问题是由两种不同的模块系统混合引起的,它们的方式不同,它们是resolved and implemented。 CommonJS modules 是动态的,而 ES6 modules 是静态可分析的。

Babel 之类的工具现在将 ES6 模块转换为 CommonJS,因为 native support is not ready yet。但是,有细微的差别。 通过使用default export (exports default),转译器发出了一个带有 default 属性的CommonJS 模块,因为在ES6 模块中可以命名和默认导出。以下示例是完全有效的 ES6 模块:

export default class Test1  
export class Test2  

这将在转译后产生 default, Test2 CommonJS 模块,并通过使用require 获得该对象作为返回值。

由于上述原因,为了在 CommonJS 中导入 ES6 模块的默认导出,您必须使用 require(module).default 语法。


调试 React.createElement: type is invalid 错误

当 React 在导入的模块出现问题时尝试渲染组件时,此错误非常常见。大多数情况下,这是由于模块中缺少export 或路径问题(相对路径是某种玩笑)而没有适当的工具,这可能会导致严重的头发拉扯。

在这种情况下,React 无法渲染通用对象 __esModule: true, default: function 并且只是抛出了一个错误。 使用require 时,可以打印出所需的模块以查看其内容,这可能有助于调试问题。


附带说明,除非您确实需要,否则请不要将 CommonJS 模块与 ES6 模块混合使用。 import/export 语法是为 ES6 模块保留的。使用 CommonJS 模块时,只需使用 module.exports 并使用 require 导入它们。将来,大多数开发人员将使用标准模块格式。在此之前,将它们混合在一起时要小心。

【讨论】:

【参考方案2】:

经常..

...就这么简单:

const MyModule = require('./MyModule');

const MyModule = require('./MyModule');

【讨论】:

非常感谢兄弟,我使用“react-data-components”模块对数据进行排序、过滤和页面导航。以前我像 ==>import DataTable from 'react-data-components' 一样导入;然后我得到了这个错误。但是在添加花括号后它工作正常。 ==> 从 'react-data-components' 导入 DataTable;我几乎浪费了3个小时的时间。再次感谢兄弟 请参考此链接::reviewdb.io/questions/1527838077232/… 用大括号括起来有什么作用?我和 OP 有同样的问题,但 有帮助【参考方案3】:

我遇到了同样的问题, 我做了这个把戏,为我工作,

您只需将export 放在class App 之前,

export class App extends Component 
  render() 
    return (
      <div className="App">
        <header className="App-header">
          <img src=logo className="App-logo"  />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
    );
  


export default App;

您还可以检查您正在使用的路由器, 我已经为我使用了这个作品,

npm install react-router-dom@next --save

【讨论】:

【参考方案4】:

以防万一其他人也遇到这种情况... 我遇到了同样的问题,但仅在运行我的 jest 测试代码时。我得到了同样的上述错误:

React.createElement: type is invalid — 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但得到:对象

如果您的项目恰好使用 typescript,但您正在使用 jest 测试(它在内部使用混合模块系统 - 包括 CommonJS require 语法),您仍然可以使用 jest if 进行此错误测试你用

import React from 'react';

子组件中的语法而不是打字稿变体:

import * as React from 'react';

这是一个奇怪的错误并且很难捕捉到,因为应用程序可以使用任何一种导入方法都可以正常运行,但是主要组件的 jest 测试可能会失败,直到子组件更新为使用第二种反应语法(同样,对于那些使用带有jest 测试的打字稿的人)。

【讨论】:

【参考方案5】:

ES6 模块令人困惑。如果我们将它们与 NodeJS 的 commonJS 模块模式混合使用,会更加混乱 ;) ,

如果您使用前端代码,我建议使用单一样式,最好使用 ES6 模块。 为了更好地理解它,我编写了一个示例应用程序。

https://github.com/Sutikshan/es-bits/tree/master/modules

【讨论】:

【参考方案6】:

对我来说,这是循环依赖的问题。

//simplistic example

//a.js
import  foo  from './b.js'
export const bar = foo

//b.js
import  bar  from './a.js'
export const foo = bar

【讨论】:

以上是关于React.createElement: type is invalid - 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但是得到:对象的主要内容,如果未能解决你的问题,请参考以下文章

react-router 报错React.createElement: type is invalid ...解决方法

React.createElement: type is invalid - 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但是得到:对象

为啥 React.createElement() 会创建一个对象?

React底层 render, createElement 方法作用梳理

React中createElement 和 cloneElement 的区别

[react] createElement与cloneElement两者有什么区别?