web-dev-qa-db-fra.com

Obtenir "Impossible d'appeler une classe en tant que fonction" dans mon projet React

J'essaie d'ajouter un composant de carte React à mon projet mais je rencontre une erreur. J'utilise le blog post de Fullstack React comme référence. J'ai localisé où l'erreur est renvoyée dans la ligne 83 de google_map.js:

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

Voici mon composant de carte jusqu'à présent. La page se charge très bien (sans carte) lorsque je commente les lignes 58 à 60, les trois dernières lignes. edit: J'ai apporté les modifications suggérées par @Dmitriy Nevzorov et me donne toujours la même erreur.

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)

Et voici où ce composant de carte est routé dans 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'))
85
Mike Fleming

Pour moi, c’est arrivé quand j’ai oublié d’écrire extends React.Component à la fin… Je sais que ce n’est pas exactement ce que VOUS aviez, mais d’autres lisant cette réponse peuvent en bénéficier, espérons-le.

147
programmer

tl; dr

Si vous utilisez React Router v4, vérifiez votre composant <Route/> si vous utilisez effectivement la propriété component pour transmettre votre composant React basé sur la classe!

Plus généralement: si votre classe semble bien fonctionner, vérifiez si le code qui l'appelle n'essaye pas de l'utiliser comme fonction.

Explication

J'ai eu cette erreur parce que j'utilisais React Router v4 et que j'avais accidentellement utilisé le prop render au lieu de celui component dans le composant <Route/> pour transmettre mon composant qui était une classe. C'était un problème, car render attend (appelle) une fonction, alors que component est celui qui fonctionnera sur les composants React.

Donc dans ce code:

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

La ligne contenant le composant <Route/> aurait dû être écrite ainsi:

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

Il est dommage qu’ils ne le vérifient pas et donnent une erreur utilisable pour une telle erreur et qu’il soit facile d’attraper une erreur.

53
totymedli

Vous avez dupliqué la déclaration export default. Le premier est remplacé par le second qui est en fait une fonction. 

9
Dmitriy Nevzorov

J'ai rencontré le même problème, il s'est produit parce que ma classe de composants ES6 n'étendait pas React.Component.

8
Jam

Pour moi, c'était ComponentName.prototype au lieu de ComponentName.propTypes. Auto suggéré par Phpstorm IDE. J'espère que ça va aider quelqu'un.

7
codersaif

Généralement, ces problèmes se produisent lorsque vous manquez l'extension Component from react:

import React, {Component} from 'react'

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

Pour moi c’est parce que j’ai utilisé prototype au lieu de propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

il devrait être 

MyComponent.propTypes = {

};
4
Onengiye Richard
Post.proptypes = {

}

à

Post.propTypes = {

}

quelqu'un devrait commenter sur la manière de surveiller cette erreur de manière très précise.

2
Mbanda

On dirait qu'il n'y a pas un seul cas où cette erreur apparaît.

Cela m'est arrivé quand je n'ai pas déclaré le constructeur dans le composant statefull.

class MyComponent extends Component {

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

au lieu de

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

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

J'ai rencontré cette erreur lorsque j'ai importé le mauvais class et que j'ai fait référence à un mauvais store lors de l'utilisation de mobx dans react-native.

J'ai fait face à une erreur dans cet extrait:

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

@inject ("counter")
@Observer

Après quelques corrections comme extrait ci-dessous. J'ai résolu mon problème de cette façon.

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

@inject("counterStore")
@observer

Ce qui n'allait vraiment pas, j'utilisais la mauvaise classe au lieu de observer J'ai utilisé Observer et au lieu de counterStore j'ai utilisé counter. J'ai résolu mon problème de cette façon.

1
badarshahzad

Pour moi, cela est arrivé parce que je n’enveloppais pas correctement ma fonction de connexion et tentais d’exporter deux composants par défaut.

1
Dmitriy

Je l'ai eu quand je l'ai fait ainsi:

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

correctement:

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

ou

const foo = ...
export default foo
1
Jeka Yaroshenko

J'ai eu un problème similaire, j'appelais la méthode de rendu de manière incorrecte

A donné une erreur:

render = () => {
    ...
}

au lieu de

correct: 

render(){
    ...
}
1
Emile Esterhuizen

Dans le fichier MyComponent.js

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

Je mets une fonction liée à ce composant:

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

export myFunction() {
...
}

puis dans un autre fichier importé cette fonction:

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

Pouvez-vous repérer le problème?

J'ai oublié les accolades et importé MyComponent sous le nom myFunction!

Donc, le correctif était:

import {myFunction} from './MyComponent'
1
Mike

Dans mon cas, en utilisant JSX, un composant parent appelait d’autres composants sans le "<>"

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

réparer 

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

Pour moi, c'est parce que j'avais accidentellement supprimé ma méthode render!

J'avais une classe avec une méthode componentWillReceiveProps dont je n'avais plus besoin, précédant immédiatement une méthode courte render. Dans ma hâte de le supprimer, j'ai accidentellement supprimé la méthode entière render.

C'était unDOULEURà traquer, car j'obtenais des erreurs de console pointant vers des commentaires dans des fichiers complètement non pertinents comme étant la "source" du problème.

0
Alex McMillan

Je l'ai expérimenté lors de l'écriture d'une instruction d'importation incorrecte lors de l'importation d'une fonction plutôt que d'une classe. Si removeMaterial est une fonction dans un autre module:

Droite:

import { removeMaterial } from './ClaimForm';

Faux:

import removeMaterial from './ClaimForm';
0
shacker

En fait, tout le problème redux connect. solutions:

Correct:

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Wrong & Bug:

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

C'est un problème général qui n'apparaît pas dans un seul cas. Mais le problème commun dans tous les cas est que vous oubliez de import un composant spécifique (peu importe que ce soit à partir d'une bibliothèque que vous avez installée ou d'un composant personnalisé que vous avez créé):

import {SomeClass} from 'some-library'

Lorsque vous l'utilisez plus tard, sans l'importer, le compilateur pense que c'est une fonction. Donc, ça casse. Ceci est un exemple commun:

imports

...code...

et puis quelque part dans votre code

<Image {..some props} />

Si vous avez oublié d'importer le composant <Image />, le compilateur ne se plaindra pas comme pour les autres importations, mais se cassera dès qu'il aura atteint votre code.

0
Tim G. Pegas

J'ai également rencontré ce problème, il est possible que vous ayez une erreur javascript dans votre composant réag. Assurez-vous que si vous utilisez une dépendance, vous utilisez l'opérateur new sur la classe pour instancier la nouvelle instance. Erreur va jeter si

this.classInstance = Class({})

utilisez plutôt

this.classInstance = new Class({})

vous verrez dans la chaîne d'erreurs dans le navigateur

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

c'est le cadeau que je crois.

0
mibbit

Dans mon cas, j'ai écrit comment à la place de Component par erreur

Je viens d'écrire ceci.

import React, { Component } from 'react';

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

Au lieu de cela.

import React, { Component } from 'react';

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

ce n'est pas grave, mais pour un débutant comme moi, c'est très déroutant ... J'espère que cela vous aidera.

0
Uddesh_jain

Essayez de vous arrêter HMR et appuyez à nouveau sur npm start pour reconstruire votre projet.
.__ Cela a fait disparaître l'erreur, je ne sais pas pourquoi. 

0
Alexander Gorelik

Un autre rapport ici: Cela n'a pas fonctionné car j'ai exporté: 

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

au lieu de 

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

Notez la position des crochets. Les deux sont corrects et ne seront pas pris par un linter ou plus joli ou quelque chose de similaire. Il m'a fallu du temps pour le retrouver. 

0

Cela s'est produit lorsque j'ai accidentellement nommé ma fonction render de manière incorrecte:

import React from 'react';

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

Mon exemple de cette erreur a été simplement causé parce que ma classe n'avait pas de méthode render appropriée.

0
Bryan Bor

Dans mon cas, j'ai accidentellement mis le nom du composant (Home) comme premier argument de la fonction connect alors qu'il était censé être à la fin. duh.

Celui-ci m'a sûrement donné l'erreur:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Mais celui-ci a fonctionné -surely- bien:

export default connect(mapStateToProps, mapDispatchToProps)(Home)
0
scaryguy