【问题标题】:Uncaught TypeError: Cannot call a class as a function未捕获的类型错误:无法将类作为函数调用
【发布时间】:2018-04-30 05:43:02
【问题描述】:

我已经浏览了这个问题的所有答案:
Getting "Cannot call a class as a function" in my React Project


我仍然无法弄清楚为什么下面会返回错误'Cannot call a class as a function'。就语法而言,我在这里遗漏了什么吗?

  • 我正在运行 Gulp、Rollup 和 Babel
  • 包含以上所有插件
  • reactDOM.render 的选择器很好,不需要导出类

代码:

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div />
        );
    }
}

// Selector is fine, changes bg to red
document.querySelector('#app').style.background = 'red';

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

错误:

使用 Rollup 和 Babel 完成 Gulp 任务:

gulp.task('js', () => {

    // Package up ES6 moduleswith stream
    const stream = plugins.rollupStream({
        input: paths.dev + '/script/app.js',
        sourcemap: true,
        format: 'iife',
        name: 'app',
        plugins: [
            plugins.rollupPluginReplace({'process.env.NODE_ENV': JSON.stringify( 'production' )}),
            plugins.rollupPluginJsx({ factory: 'React.createElement' }),
            plugins.rollupPluginCommonjs({}),           
            plugins.rollupPluginNodeResolve({ jsnext: true, main: true }),
            plugins.rollupPluginIncludepaths({ paths: [paths.dev + '/script/'] })
        ]
    })

    return stream
        .on('error', e => {
            console.error(e.stack);

            notifier.notify({
                title: 'Rollup error',
                message: e.stack
            });
            stream.emit('end');
        })
        // Error handling
        .pipe(plugins.plumber())
        // Prepare files for sourcemap
        .pipe(plugins.vinylSourceStream('app.js', paths.dev + '/script/'))
        .pipe(plugins.vinylBuffer())
        .pipe(plugins.sourcemaps.init({ loadMaps: true }))
        // Convert ES6
        .pipe(plugins.babel({ presets: ['es2015', 'react'] }))
        // Write sourcemap
        .pipe(plugins.sourcemaps.write('.'))
        .pipe(gulp.dest(paths.tmp + '/script/'))
        .pipe(plugins.browserSync.stream());
});

代码库:

https://github.com/alexplummer/framework-react/blob/master/_dev/script/app.js

【问题讨论】:

  • 你导出 App 类了吗?
  • 您是否尝试过在您的index.html 中使用&lt;div id="#main"/&gt; 代替document.getElementById('main'),?否则,您的代码看起来是正确的。
  • 是的,选择器没问题,不管有没有 id 都是一样的问题。
  • 你可以尝试在constructor(props) 和调用super(props) 时添加道具吗?
  • 你忘了import ReactDOM from 'react-dom

标签: javascript reactjs npm gulp babeljs


【解决方案1】:

问题是您的 JSX 未正确转译。如果您查看 devtools 中的输出(堆栈跟踪中倒数第二个错误),您会看到该类被作为常规函数调用:

reactDom.render(App(), document.querySelector('#app'));
//              ^^^^^

您使用的是rollup-plugin-jsx,它的处理方式似乎有所不同。如果你仍然使用 Babel,真的没有理由使用它,因为 Babel 也可以转换你的 JSX。我假设你已经添加了这个,因为 Rollup 抱怨 JSX。那是因为您的构建管道不太正确。您目前首先将代码与 Rollup 捆绑在一起,然后在其上运行 Babel。

您可以使用rollup-plugin-babel 将 Babel 直接集成到 Rollup 中,因此 Rollup 捆绑的所有内容都将由 Babel 自动转译。通过添加此插件,您可以完全删除 rollup-plugin-jsx,之后您也不需要将其通过管道传递给 Babel。

这些是对tasks/js.js 的更改(Stack Overflow 没有针对 git diffs 的语法突出显示,但您可以在 Gist - tasks/js.js diff 中看到突出显示的版本):

diff --git a/tasks/js.js b/tasks/js.js
index 0caabc1..7c5319d 100644
--- a/tasks/js.js
+++ b/tasks/js.js
@@ -70,7 +70,10 @@ gulp.task('js', () => {
                name: 'app',
                plugins: [
                        plugins.rollupPluginReplace({'process.env.NODE_ENV': JSON.stringify( 'development' )}),
-                       plugins.rollupPluginJsx({ factory: 'React.createElement' }),
+                       plugins.rollupPluginBabel({
+                               exclude: 'node_modules/**',
+                               presets: [['es2015', { modules: false }], 'react']
+                       }),
                        plugins.rollupPluginCommonjs({}),
                        plugins.rollupPluginNodeResolve({ jsnext: true, main: true }),
                        plugins.rollupPluginIncludepaths({ paths: [paths.dev + '/script/'] })
@@ -93,8 +96,6 @@ gulp.task('js', () => {
                .pipe(plugins.vinylSourceStream('app.js', paths.dev + '/script/'))
                .pipe(plugins.vinylBuffer())
                .pipe(plugins.sourcemaps.init({ loadMaps: true }))
-               // Convert ES6
-               .pipe(plugins.babel({ presets: ['es2015', 'react'] }))
                // Write sourcemap
                .pipe(plugins.sourcemaps.write('.'))
                .pipe(gulp.dest(paths.tmp + '/script/'))

注意,Babel 中需要关闭模块转译,因为 Rollup 需要 ES 模块。在旁注中,babel-preset-es2015 已被弃用,取而代之的是 babel-preset-env,其中包含 es201x 预设所做的一切以及更多。它是es2015 的直接替代品,详情请参阅Migration guide from es2015 to env

【讨论】:

  • 我也遇到了同样的问题,但不是 Babel 忘记说new App()...是我。
猜你喜欢
  • 1970-01-01
  • 2021-12-23
  • 1970-01-01
  • 2018-10-21
  • 2020-12-01
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多