155

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'))
Mike Fleming
  • 2,593
  • 4
  • 14
  • 24
  • 3
    You have two `export default`s, and would it be `new GoogleAPIComponent()` not `GoogleAPIComponent()`? – gcampbell Jul 20 '16 at 13:05
  • I removed one of the defaults and tried your suggestion. It looks like it is actually talking to Google Maps now, which is good, but before the page can load it throws another cryptic error: Locations.js:58 Uncaught TypeError: (intermediate value) is not a function". Any ideas? – Mike Fleming Jul 20 '16 at 16:54
  • 1
    What if you remove the `(LocationContainer)`? – gcampbell Jul 20 '16 at 17:02
  • Thanks, I think that got it! Weird, that's how they have it written on their blog post. Still getting a few other errors from Google Maps, I'll put them here: 'GoogleMap: apiKey is deprecated, use bootstrapURLKeys={{key: YOUR_API_KEY}} instead. google_map.js:689 GoogleMap: center or defaultCenterproperty must be defined google_map.js:699 GoogleMap: zoom or defaultZoomproperty must be defined google_map.js: 704' – Mike Fleming Jul 20 '16 at 17:20
  • 1
    I'm not sure about the other errors, but you could try this to fix the first one: `export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })` – gcampbell Jul 20 '16 at 17:33
  • Thanks, that took care of that. I ran into more issues with this repo not being able to mesh well with the existing project and the API so I scrapped it and used [React-Gmap](https://github.com/MicheleBertoli/react-gmaps) instead. I spent about a day using this repo and within an hour I had the other up and running. Thanks again for all your help! – Mike Fleming Jul 21 '16 at 13:08
  • Check that you're missing `new` when trying to initiate a class – onmyway133 Jan 10 '19 at 15:09

32 Answers32

224

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.

lambda
  • 3,295
  • 1
  • 26
  • 32
programmer
  • 3,043
  • 1
  • 22
  • 30
  • 21
    There's great post at overreacted that explains why this works https://overreacted.io/how-does-react-tell-a-class-from-a-function/ – Eric Kigathi Dec 03 '18 at 15:48
  • 3
    Summary of post: Distinguishing between a class and a function in browser is actually not completely trivial ... "The actual solution is really simple, but \[I'm going on a\] huge tangent to explain why React ended up with this solution ..." blah, blah, blah, ... -> "If you don’t extend React.Component, React won’t find isReactComponent on the prototype, and won’t treat component as a class." – spinkus Jul 22 '20 at 01:41
  • Great. I was facing the similar issue & your solution fixed the issue. But my syntax was `import React, { Component } from 'react'; class extends Component`. I couldn't understand how did this resolve the issue by replacing `Component` with `React.Component`. Does the import matters? – Arun Ramachandran Aug 02 '20 at 18:42
114

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!
William Park
  • 1,697
  • 1
  • 12
  • 17
  • 2
    This solved my problem, I was using a different use case not the animated but after using the new keyword solved it. Thank you – Olivier JM Nov 16 '18 at 06:49
  • 10
    Spent 4 hours 44 minutes and 4 seconds trying to know wth happened. You are god. – Satheesh Jul 04 '19 at 15:19
  • Yup, that was me too. Thank you! – James Cushing Sep 08 '19 at 17:17
  • Does someone know in which version it changed? (another thing to worry about RN) –  Mar 22 '21 at 15:42
  • The same exact thing happened to me, and I mean Exact (down to the variable name). Creepy... – Akin Williams Oct 21 '21 at 18:08
  • 1
    @AkinWilliams I am you from the future. I went back in time to save you from this misery. – William Park Oct 26 '21 at 09:07
  • After crawling all over the place in a vain attempt to resolve my problem, this simple fix was wot dun it for me (Brits will understand that)! Thank you so much! I was going spare! Incidentally, my issue was with a plan vanilla script. I don't use React so your solution may work in other contexts too. – Thomas Murphy Jun 22 '22 at 10:15
  • 1
    @ThomasMurphy Glad to help! You're absolutely right. It has been 5 years since I answered this question, and I understand the issue more now. The most common cause for this issue will be that you've missed `new` keyword somewhere. By using the `new` keyword, you're creating an instance of a class, rather than referencing the class itself. – William Park Jun 22 '22 at 13:15
66

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.

Community
  • 1
  • 1
totymedli
  • 29,531
  • 22
  • 131
  • 165
52

Happened to me because I used

PropTypes.arrayOf(SomeClass)

instead of

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))

Dan Balaban
  • 735
  • 8
  • 10
  • Thanks, wrong PropTypes definition was the issue in my case. – Vasiliy Oct 10 '17 at 08:02
  • this solved my issue! was `PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,` instead of `PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,` – Doug Sep 05 '18 at 14:23
  • Thanks, was really wondering for a long time what was going wrong there! – Got The Fever Media Apr 07 '20 at 12:14
17

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

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
codersaif
  • 946
  • 9
  • 15
16

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

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Jam
  • 296
  • 2
  • 8
15

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

Dmitriy Nevzorov
  • 6,042
  • 1
  • 20
  • 28
  • Good catch! I left the default in front of GoogleApiComponent and I still get the same error. Alternatively, removing all defaults gives me an "unexpected token" error in my terminal on GoogleApiComponent. – Mike Fleming Jul 20 '16 at 14:04
8

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

import React, {Component} from 'react'

export default class TimePicker extends Component {
    render() {
        return();     
    }
}
rocambille
  • 15,398
  • 12
  • 50
  • 68
jeff ayan
  • 819
  • 1
  • 13
  • 16
7

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 = {

};
Onengiye Richard
  • 348
  • 6
  • 12
6
Post.proptypes = {

}

to

Post.propTypes = {

}

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

Mbanda
  • 968
  • 11
  • 21
6

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)
Dipen Dedania
  • 1,452
  • 1
  • 21
  • 37
5

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.

Tim Pegas
  • 372
  • 4
  • 6
4

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>;
    }
}
Pavlo Kozlov
  • 966
  • 1
  • 9
  • 22
2

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'
Mikhail Vasin
  • 2,421
  • 1
  • 24
  • 31
2

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;
airvine
  • 631
  • 8
  • 23
1

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.

Alex McMillan
  • 17,096
  • 12
  • 55
  • 88
1

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

Gave an error:

render = () => {
    ...
}

instead of

correct:

render(){
    ...
}
1

I had it when I did so :

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

correctly:

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

or

const foo = ...
export default foo
Je ka
  • 43
  • 5
1

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

Dmitriy
  • 1,211
  • 1
  • 11
  • 28
1

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.

badarshahzad
  • 1,227
  • 16
  • 25
1

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';
shacker
  • 14,712
  • 8
  • 89
  • 89
0

I have also run into this, it is possible you have a javascript error inside of your react component. Make sure if you are using a dependency you are using the new operator on the class to instantiate the new instance. Error will throw if

this.classInstance = Class({})

instead use

this.classInstance = new Class({})

you will see in the error chain in the browser

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

that is the giveaway I believe.

mibbit
  • 4,997
  • 3
  • 26
  • 34
0

In my case i wrote comment in place of Component by mistake

I just wrote this.

import React, { Component } from 'react';

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

Instead of this.

import React, { Component } from 'react';

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

it's not a big deal but for a beginner like me it's really confusing. I hope this will be helpfull.

Uddesh Jain
  • 1,064
  • 2
  • 15
  • 16
0

In my case, using JSX a parent component was calling other components without the "<>"

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

fix

<ComponentA someProp={someCheck ? <ComponentX /> : <ComponentY />} />
Alan
  • 470
  • 4
  • 10
0

Another report here: It didn't work as I exported:

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

instead of

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

Note the position of the brackets. Both are correct and won't get caught by either a linter or prettier or something similar. Took me a while to track it down.

Sebastijan Dumančić
  • 1,165
  • 1
  • 11
  • 20
0

In my case, I accidentally put component name (Home) as the first argument to connect function while it was supposed to be at the end. duh.

This one -surely- gave me the error:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

But this one worked -surely- fine:

export default connect(mapStateToProps, mapDispatchToProps)(Home)
scaryguy
  • 7,720
  • 3
  • 36
  • 52
0

This occured when I accidentally named my render function incorrectly:

import React from 'react';

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

My instance of this error was simply caused because my class did not have a proper render method.

Bryan Bor
  • 21
  • 1
0

Actually all the problem redux connect. solutions:

Correct:

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Wrong & Bug:

export default connect(PageName)(mapStateToProps, mapDispatchToProps)
0

In my scenario I was attempting to use hot reloading on a custom hook (not sure why, probably just muscle memory when creating components).

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

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

The correct way

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

export default useCustomHook;

Apparently you can't hot reload hook

Bryant
  • 156
  • 2
  • 7
0

In my case I accidentally called objectOf

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

Instead of instanceOf:

static propTypes = {
    appStore: PropTypes.instanceOf(AppStore).isRequired
}
Jaroslav Kuboš
  • 663
  • 7
  • 17
-1

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

Example

import settings from './pages/Settings';

But sure it should be

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

Where settings directory contains following files actions.js, index.js, reducer.js.

To check it you can log reducers arg of the assertReducerShape() function from the redux/es/redux.js.

-2

If you're on Node JS and you're seeing this error in a Class you've added to support a Cucumber test, it's because Cucumber will automatically try to run anything that exports a function, and NodeJS internally converts a Class to a function.

So instead of this:

module.exports = MyClass;

do this:

module.exports.MyClass = MyClass;

Then, when you import it into your steps file, do it like this:

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

This way you're not exporting a function. Read more here.

Ryan Shillington
  • 23,006
  • 14
  • 93
  • 108