在我的 React 项目中得到“不能调用类作为函数”

我试图添加一个反应映射组件到我的项目,但遇到了一个错误。我正在使用富尔斯塔克反应的 博客文章作为参考。我找到了在 google _ map 中出现错误的地方。Js 第83行:

function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}

这是我目前为止的地图组件。当我注释掉第58-60行(最后三行)时,页面加载得很好(没有地图)。编辑: 我按照@Dmitriy Nevzorov 的建议进行了修改,但仍然出现了同样的错误。

import React from 'react'
import GoogleApiComponent from 'google-map-react'


export class LocationsContainer extends React.Component {
constructor() {
super()
}
render() {
const style = {
width: '100vw',
height: '100vh'
}
return (
<div style={style}>
<Map google={this.props.google} />
</div>
)
}
}


export class Map extends React.Component {
componentDidUpdate(prevProps, prevState){
if (prevProps.google !== this.props.google){
this.loadMap();
}
}
componentDidMount(){
this.loadMap();
}
loadMap(){
if (this.props && this.props.google){
const {google} = this.props;
const maps = google.maps;


const mapRef = this.refs.map;
const node = ReactDOM.findDOMNode(mapRef);


let zoom = 14;
let lat = 37.774929
let lng = 122.419416
const center = new maps.LatLng(lat, lng);
const mapConfig = Object.assign({}, {
center: center,
zoom: zoom
})
this.map = new maps.Map(node, mapConfig)
}
}
render() {
return (
<div ref='map'>
Loading map...
</div>
)
}
}


export default GoogleApiComponent({
apiKey: MY_API_KEY
})(LocationsContainer)

下面是这个 map 组件在 main.js 中的路由:

import {render} from 'react-dom';
import React from 'react';
import Artists from './components/Artists'
import { Router, Route, Link, browserHistory } from 'react-router'
import Home from './components/HomePage'
import Gallery from './components/ArtGallery'
import ArtistPage from './components/ArtistPage'
import FavsPage from './components/FavsPage'
import LocationsContainer from './components/Locations'


//Create the route configuration
render((
<Router history={browserHistory}>
<Route path="/" component={Home} />
<Route path="locations" component={LocationsContainer} />
<Route path="artists" component={Artists} />
<Route path="gallery" component={Gallery} />
<Route path="favorites" component={FavsPage} />
<Route path=":artistName" component={ArtistPage} />
</Router>
), document.getElementById('app'))
215179 次浏览

您已经复制了 export default声明。第一个声明被第二个声明覆盖,第二个声明实际上是一个函数。

对我来说,它发生在我忘记在结尾写 extends React.Component的时候。 我知道这不完全是你所拥有的,但是其他读到这个答案的人可以从中受益,希望如此。

我也遇到了同样的问题,因为我的 ES6组件类没有扩展 React.Component

发生在我身上是因为

PropTypes.arrayOf(SomeClass)

而不是

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))

博士

如果您使用反应路由器 v4检查您的 <Route/>组件,如果您确实使用 component道具传递您的基于类的反应组件!

更一般地说: 如果您的类看起来不错,检查调用它的代码是否尝试将它用作函数。

解释

之所以出现这个错误,是因为我使用的是 React Router v4,我不小心使用了 render道具而不是 <Route/>组件中的 component道具来传递类组件。这是一个问题,因为 render期望(调用)一个函数,而 component将在 React 组件上工作。

所以在这段代码里:

<HashRouter>
<Switch>
<Route path="/" render={MyComponent} />
</Switch>
</HashRouter>

包含 <Route/>组件的代码行应该是这样写的:

<Route path="/" component={MyComponent} />

这是一个耻辱,他们没有检查它,并提供了一个有用的错误,这样的和容易捕捉到的错误。

对我来说,这是因为我不小心删除了我的 render方法!

我有一个类的 componentWillReceiveProps方法我不再需要了,紧接着是一个简短的 render方法。在匆忙删除它的过程中,我也意外地删除了整个 render方法。

这是一个需要跟踪的 痛苦,因为我得到的控制台错误指向完全不相关的文件中的注释,认为这是问题的“源”。

看起来出现这个错误的情况不止一个。

当我没有在状态完整的组件中声明构造函数时就发生了这种情况。

class MyComponent extends Component {


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

而不是

class MyComponent extends Component {


constructor(props) {
super(props);
}


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

我也遇到过这种情况,可能是你的 response 组件内部出现了 javascript 错误。确保如果您正在使用依赖项,那么您正在使用类上的 new操作符来实例化新实例。错误将抛出如果

this.classInstance = Class({})

而不是使用

this.classInstance = new Class({})

您将在浏览器的错误链中看到

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

我相信这就是暴露。

我有一个类似的问题,我调用渲染方法不正确

给出了一个错误:

render = () => {
...
}

而不是

正确:

render(){
...
}

对我来说,这是因为我忘记使用 new关键字时,设置动画状态。

例如:

fadeAnim: Animated.Value(0),

fadeAnim: new Animated.Value(0),

会解决的。


5年后编辑更多解释:

最有可能的问题是你在某处遗漏了 new关键字,就像我上面所做的那样。这意味着您甚至不需要使用 React 来处理这个错误。

问题在于,在 JS 中可以创建这样的类(MDN 中的示例) :

class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}


calcArea() {
return this.height * this.width;
}


}

如果你想使用这个类,你需要像这样创建一个 新的例子:

const rect = new Rect(height, width);

出现这个问题的原因通常是您试图调用类的 定义(或定义中的某个内容) ,而不是类的 例子

本质上,在代码中,你是这样做的:

Rectangle.calcArea() // incorrect!

当你应该做的时候

rect.calcArea() // correct!

大多数情况下,这些问题发生在你错过从反应扩展 组件时:

import React, {Component} from 'react'


export default class TimePicker extends Component {
render() {
return();
}
}

如果你在 Node JS 上,并且你在一个类中看到了这个错误,这个类是你为了支持一个黄瓜测试而添加的,这是因为黄瓜会自动尝试运行任何导出函数的东西,而 NodeJS 在内部将一个类转换成一个函数。

所以不是这样:

module.exports = MyClass;

这样做:

module.exports.MyClass = MyClass;

然后,当您将它导入到您的步骤文件中时,如下所示:

let MyClass = require("myclass.js").MyClass;

这样就不用导出函数了。

对我来说,是 ComponentName.prototype而不是 ComponentName.propTypes。 由 Phpstorm IDE 自动建议,希望对大家有所帮助。

当我这样做的时候:

function foo() (...) export default foo

正确地说:

export default  () =>(...);

或者

const foo = ...
export default foo

对我来说,发生这种情况是因为我没有正确地包装连接函数,并试图导出默认的两个组件

当我导入错误的 同学们并引用错误的 商店时,我遇到了这个错误。

我在这个片段中遇到了错误:

import { inject, Observer } from "mobx-react";


@inject ("counter")
@Observer

经过一些修正后,比如下面的代码片段。我就这样解决了我的问题。

import { inject, observer } from "mobx-react";


@inject("counterStore")
@observer

实际上是错误的,我使用了错误的类而不是 observer,我使用了 Observer而不是 counterStore,我使用了 counter。我就这样解决了我的问题。

For me it was a wrong import of a reducer in the rootReducer.js. I imported container instead of reducer file.

例子

import settings from './pages/Settings';

当然应该是

import settings from './pages/Settings/reducer';

其中设置目录包含以下文件 actions.js、 index.js、 reducer.js。

要检查它,可以从 redux/es/redux.js 记录 assertReducerShape ()函数的 reducers 参数。

在我的案例中,我错误地用 comment代替了 Component

我刚写了这个。

import React, { Component } from 'react';


class Something extends Component{
render() {
return();
}
}

而不是这样。

import React, { Component } from 'react';


class Something extends comment{
render() {
return();
}
}

这没什么大不了的,但对于像我这样的初学者来说,这真的很令人困惑。 我希望这能有所帮助。

在文件 MyComponent.js

export default class MyComponent extends React.Component {
...
}

我加入了一些与该组件相关的函数:

export default class MyComponent extends React.Component {
...
}


export myFunction() {
...
}

然后在另一个文件中导入该函数:

import myFunction from './MyComponent'
...
myFunction() // => bang! "Cannot call a class as a function"
...

你能发现问题所在吗?

我忘了带花括号,用 myFunction名字导入了 MyComponent

所以,解决办法是:

import {myFunction} from './MyComponent'

当我在导入函数而不是类时写错了 import 语句时,我经历了这种情况。如果 removeMaterial是另一个模块中的函数:

右图:

import { removeMaterial } from './ClaimForm';

错:

import removeMaterial from './ClaimForm';

在我的例子中,使用 JSX 父组件调用其他组件时没有使用“ < >”

 <ComponentA someProp={someCheck ? ComponentX : ComponentY} />

修好

<ComponentA someProp={someCheck ? <ComponentX /> : <ComponentY />} />

对我来说,这是因为我使用原型而不是 道具类型

class MyComponent extends Component {


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


MyComponent.prototype = {


};

应该是的

MyComponent.propTypes = {


};

这里的另一个报告: 它在我出口的时候不起作用:

export default compose(
injectIntl,
connect(mapStateToProps)(Onboarding)
);

而不是

export default compose(
injectIntl,
connect(mapStateToProps)
)(Onboarding);

注意括号的位置。两者都是正确的,都不会被衬垫或者更漂亮的东西或者类似的东西抓住。我花了点时间才找到。

在我的例子中,我意外地将组件名(Home)作为 connect函数的第一个参数,而它应该在函数的末尾。废话。

这个问题——毫无疑问——给了我错误的答案:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

但这一招确实奏效:

export default connect(mapStateToProps, mapDispatchToProps)(Home)
Post.proptypes = {


}

Post.propTypes = {


}

有人应该评论如何以一种非常精确的方式监测这种错误。

当我不小心将 render函数命名错误时,就发生了这种情况:

import React from 'react';


export class MyComponent extends React.Component {
noCalledRender() {
return (
<div>
Hello, world!
</div>
);
}
}

这个错误的实例仅仅是因为我的类没有合适的 render方法。

这是一个普遍的问题,不会出现在单个案例中。但是,在所有的情况下,常见的问题是您忘记了 import一个特定的组件(不管它是来自您安装的库还是您创建的自定义组件) :

import {SomeClass} from 'some-library'

当您以后使用它时,不需要导入它,编译器就会认为它是一个函数。因此,它断裂了。这是一个常见的例子:

imports

...code...

然后在代码的某个地方

<Image {..some props} />

如果您忘记导入组件 <Image />,那么编译器将不会像对待其他导入那样抱怨,而是在到达代码时中断。

实际上所有的问题都是相互联系的。解决方案:

正确 :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

错误 & 错误 :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)

我因犯了一个小错误而得到了这个错误。我的错误是将类作为函数而不是类导出。在我的课程档案的底部,我有:

export default InputField();

本该是:

export default InputField;

有两件事你可以检查一下,

class Slider extends React.Component {
// Your React Code
}


Slider.propTypes = {
// accessibility: PropTypes.bool,
}
  • 确保扩展了 反应,成分
  • 使用 道具类型代替原型(根据 IDE 智能感知)

在我的场景中,我试图在自定义钩子上使用热重载(不知道为什么,可能只是在创建组件时的肌肉内存)。

const useCustomHook = () => {
const params = useParams();
return useSelector(
// Do things
);
};


// The next line is what breaks it
export default hot(module)(useCustomHook);

正确的方式

const useCustomHook = () => {
const params = useParams();
return useSelector(
// Do things
);
};


export default useCustomHook;

显然你不能热重新装弹钩

在我的情况下,我意外地调用 对象

static propTypes = {
appStore: PropTypes.objectOf(AppStore).isRequired
}

代替 InstanceOf:

static propTypes = {
appStore: PropTypes.instanceOf(AppStore).isRequired
}