我查看了这个问题的所有答案:
Getting "Cannot call a class as a function" in my React Project
我仍然无法解决为什么以下错误'无法将类称为函数'。我在语法方面遗漏了什么吗?
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
答案 0 :(得分: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。