Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting "Cannot call a class as a function" in my React Project

I'm trying to add a React map component to my project but run into an error. I'm using Fullstack React's blog post as a reference. I tracked down where the error gets thrown in google_map.js line 83:

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

Here is my map component so far. The page loads just fine (without a map) when I comment out lines 58-60, the last three lines. edit: I made the changes that @Dmitriy Nevzorov suggested and it still gives me the same error.

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)

And here is where this map component gets routed in 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'))
like image 956
Mike Fleming Avatar asked Jul 20 '16 12:07

Mike Fleming


People also ask

How do you call a function in React?

In React, the onClick handler allows you to call a function and perform an action when an element is clicked. onClick is the cornerstone of any React app. Click on any of the examples below to see code snippets and common uses: Call a Function After Clicking a Button.

Can I use class in React JS?

React class based components are the bread and butter of most modern web apps built in ReactJS. These components are simple classes (made up of multiple functions that add functionality to the application). All class based components are child classes for the Component class of ReactJS.


21 Answers

For me it happened when I forgot to write extends React.Component at the end. I know it's not exactly what YOU had, but others reading this answer can benefit from this, hopefully.

like image 96
programmer Avatar answered Oct 04 '22 07:10

programmer


For me it was because I forgot to use the new keyword when setting up Animated state.

eg:

fadeAnim: Animated.Value(0),

to

fadeAnim: new Animated.Value(0),

would fix it.


Edit from 5 years on with more explanation:

The most likely issue is that you're missing the new keyword somewhere, just like I did above. What this means is you don't even need to be using React to come across this error.

The issue is that in JS you can create classes like so (Example from MDN):

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

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

}

If you wanted to use this class, you need to create a new instance of it like so:

const rect = new Rect(height, width);

The reason for this problem is often you're trying to do a function call to the definition of the class (or something inside the definition), rather than an instance of the class.

Essentially, in code, you're doing this:

Rectangle.calcArea() // incorrect!

when you should be doing

rect.calcArea() // correct!
like image 24
William Park Avatar answered Oct 04 '22 09:10

William Park


tl;dr

If you use React Router v4 check your <Route/> component if you indeed use the component prop to pass your class based React component!

More generally: If your class seems ok, check if the code that calls it doesn't try to use it as a function.

Explanation

I got this error because I was using React Router v4 and I accidentally used the render prop instead of the component one in the <Route/> component to pass my component that was a class. This was a problem, because render expects (calls) a function, while component is the one that will work on React components.

So in this code:

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

The line containing the <Route/> component, should have been written like this:

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

It is a shame, that they don't check it and give a usable error for such and easy to catch mistake.

like image 36
totymedli Avatar answered Oct 04 '22 08:10

totymedli


Happened to me because I used

PropTypes.arrayOf(SomeClass)

instead of

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))

like image 41
Dan Balaban Avatar answered Oct 04 '22 07:10

Dan Balaban


For me, it was ComponentName.prototype instead of ComponentName.propTypes. auto suggested by Phpstorm IDE. Hope it will help someone.

like image 25
codersaif Avatar answered Oct 04 '22 07:10

codersaif


You have duplicated export default declaration. The first one get overridden by second one which is actually a function.

like image 35
Dmitriy Nevzorov Avatar answered Oct 04 '22 09:10

Dmitriy Nevzorov


I experienced the same issue, it occurred because my ES6 component class was not extending React.Component.

like image 31
Jam Avatar answered Oct 04 '22 07:10

Jam


Mostly these issues occur when you miss extending Component from react:

import React, {Component} from 'react'

export default class TimePicker extends Component {
    render() {
        return();     
    }
}
like image 29
jeff ayan Avatar answered Oct 04 '22 09:10

jeff ayan


For me it was because i used prototype instead of propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

it ought to be

MyComponent.propTypes = {

};
like image 21
Onengiye Richard Avatar answered Oct 04 '22 08:10

Onengiye Richard


Two things you can check is,

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Make sure that you extends React.Component
  • Use propTypes instead of prototype (as per IDE intellisense)
like image 20
Dipen Dedania Avatar answered Oct 04 '22 08:10

Dipen Dedania


Post.proptypes = {

}

to

Post.propTypes = {

}

someone should comment on how to monitor such error in a very precise way.

like image 45
Mbanda Avatar answered Oct 04 '22 07:10

Mbanda


Looks like there're no single case when this error appears.

Happened to me when I didn't declare constructor in statefull component.

class MyComponent extends Component {

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

instead of

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return <div>Test</div>;
    }
}
like image 34
Pavlo Kozlov Avatar answered Oct 04 '22 08:10

Pavlo Kozlov


This is a general issue, and doesn't appear in a single case. But, the common problem in all the cases is that you forget to import a specific component (doesn't matter if it's either from a library that you installed or a custom made component that you created):

import {SomeClass} from 'some-library'

When you use it later, without importing it, the compiler thinks it's a function. Therefore, it breaks. This is a common example:

imports

...code...

and then somewhere inside your code

<Image {..some props} />

If you forgot to import the component <Image /> then the compiler will not complain like it does for other imports, but will break when it reaches your code.

like image 21
Tim Pegas Avatar answered Oct 04 '22 07:10

Tim Pegas


In file MyComponent.js

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

I put some function related to that component:

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

export myFunction() {
...
}

and then in another file imported that function:

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

Can you spot the problem?

I forgot the curly braces, and imported MyComponent under name myFunction!

So, the fix was:

import {myFunction} from './MyComponent'
like image 45
Mikhail Vasin Avatar answered Oct 04 '22 07:10

Mikhail Vasin


I received this error by making small mistake. My error was exporting the class as a function instead of as a class. At the bottom of my class file I had:

export default InputField();

when it should have been:

export default InputField;
like image 35
airvine Avatar answered Oct 04 '22 09:10

airvine


For me, it was because I'd accidentally deleted my render method !

I had a class with a componentWillReceiveProps method I didn't need anymore, immediately preceding a short render method. In my haste removing it, I accidentally removed the entire render method as well.

This was a PAIN to track down, as I was getting console errors pointing at comments in completely irrelevant files as being the "source" of the problem.

like image 37
Alex McMillan Avatar answered Oct 04 '22 07:10

Alex McMillan


I had a similar problem I was calling the render method incorrectly

Gave an error:

render = () => {
    ...
}

instead of

correct:

render(){
    ...
}
like image 23
Emile Esterhuizen Avatar answered Oct 04 '22 07:10

Emile Esterhuizen


I had it when I did so :

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

correctly:

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

or

const foo = ...
export default foo
like image 24
Je ka Avatar answered Oct 04 '22 09:10

Je ka


For me it happened because I didn't wrap my connect function properly, and tried to export default two components

like image 22
Dmitriy Avatar answered Oct 04 '22 07:10

Dmitriy


I faced this error when I imported the wrong class and referred to wrong store while using mobx in react-native.

I faced error in this snippet :

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

@inject ("counter")
@Observer

After few corrections like as below snippet. I resolved my issue like this way.

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

@inject("counterStore")
@observer

What was actually wrong,I was using the wrong class instead of observer I used Observer and instead of counterStore I used counter. I solved my issue like this way.

like image 38
badarshahzad Avatar answered Oct 04 '22 09:10

badarshahzad


I experienced this when writing an import statement wrong while importing a function, rather than a class. If removeMaterial is a function in another module:

Right:

import { removeMaterial } from './ClaimForm';

Wrong:

import removeMaterial from './ClaimForm';
like image 26
shacker Avatar answered Oct 04 '22 07:10

shacker