Getting "Cannot call a class as a function" in my React Project
JavascriptGoogle MapsReactjsEcmascript 6React RouterJavascript Problem Overview
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'))
Javascript Solutions
Solution 1 - Javascript
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.
Solution 2 - Javascript
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.
Solution 3 - Javascript
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.
Solution 4 - Javascript
Happened to me because I used
PropTypes.arrayOf(SomeClass)
instead of
PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))
Solution 5 - Javascript
For me, it was ComponentName.prototype
instead of ComponentName.propTypes
.
auto suggested by Phpstorm
IDE. Hope it will help someone.
Solution 6 - Javascript
You have duplicated export default
declaration. The first one get overridden by second one which is actually a function.
Solution 7 - Javascript
I experienced the same issue, it occurred because my ES6
component class was not extending React.Component
.
Solution 8 - Javascript
Mostly these issues occur when you miss extending Component from react:
import React, {Component} from 'react'
export default class TimePicker extends Component {
render() {
return();
}
}
Solution 9 - Javascript
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 = {
};
Solution 10 - Javascript
Post.proptypes = {
}
to
Post.propTypes = {
}
someone should comment on how to monitor such error in a very precise way.
Solution 11 - Javascript
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)
Solution 12 - Javascript
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>;
}
}
Solution 13 - Javascript
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.
Solution 14 - Javascript
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'
Solution 15 - Javascript
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;
Solution 16 - Javascript
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.
Solution 17 - Javascript
I had a similar problem I was calling the render method incorrectly
Gave an error:
render = () => {
...
}
instead of
correct:
render(){
...
}
Solution 18 - Javascript
I had it when I did so :
function foo() (...) export default foo
correctly:
export default () =>(...);
or
const foo = ...
export default foo
Solution 19 - Javascript
For me it happened because I didn't wrap my connect function properly, and tried to export default two components
Solution 20 - Javascript
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.
Solution 21 - Javascript
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';
Solution 22 - Javascript
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.
Solution 23 - Javascript
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.
Solution 24 - Javascript
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 />} />
Solution 25 - Javascript
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.
Solution 26 - Javascript
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)
Solution 27 - Javascript
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.
Solution 28 - Javascript
Actually all the problem redux connect. solutions:
Correct:
export default connect(mapStateToProps, mapDispatchToProps)(PageName)
Wrong & Bug:
export default connect(PageName)(mapStateToProps, mapDispatchToProps)
Solution 29 - Javascript
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
Solution 30 - Javascript
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.
Solution 31 - Javascript
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.