【问题标题】:React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: objectReact.createElement: type is invalid - 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但是得到:对象
【发布时间】: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: function}default.nameApp。我的路径是正确的,因为 commonJS 方式 module.exports 有效。
  • 那么你应该使用const App = require('./components/App').default来获取组件(默认导出)。

标签: javascript reactjs ecmascript-6 export commonjs


【解决方案1】:

您遇到的问题是由两种不同的模块系统混合引起的,它们的方式不同,它们是resolved and implementedCommonJS 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个小时的时间。再次感谢兄弟
    • 用大括号括起来有什么作用?我和 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" alt="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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-09-05
            • 1970-01-01
            • 2018-11-29
            • 2019-08-06
            • 1970-01-01
            • 2017-06-03
            • 1970-01-01
            相关资源
            最近更新 更多