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


130

J'essaie d'ajouter un composant de carte React à mon projet mais je rencontre une erreur. J'utilise l'article de blog de Fullstack React comme référence. J'ai retracé l'emplacement de l'erreur 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 fait les changements suggérés par @Dmitriy Nevzorov et cela 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 acheminé 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'))

2
Vous avez deux export defaults, et n'est-ce new GoogleAPIComponent()pas GoogleAPIComponent()?
gcampbell

J'ai supprimé l'un des paramètres par défaut et essayé votre suggestion. On dirait qu'il parle en fait à Google Maps maintenant, ce qui est bien, mais avant que la page ne puisse se charger, il génère une autre erreur cryptique: Locations.js: 58 Uncaught TypeError: (valeur intermédiaire) n'est pas une fonction ". Des idées?
Mike Fleming

1
Et si vous supprimez le (LocationContainer)?
gcampbell

Merci, je pense que c'est compris! Bizarre, c'est comme ça qu'ils l'ont écrit sur leur blog. Je reçois encore quelques autres erreurs de Google Maps, je les mets ici: "GoogleMap: apiKey est obsolète, utilisez plutôt bootstrapURLKeys = {{key: YOUR_API_KEY}}. google_map.js: 689 GoogleMap: center ou defaultCenterproperty doit être défini google_map.js: 699 GoogleMap: zoom ou defaultZoomproperty doit être défini google_map.js: 704 '
Mike Fleming

1
Je ne suis pas sûr des autres erreurs, mais vous pouvez essayer ceci pour corriger la première:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

Réponses:


207

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 personnes lisant cette réponse peuvent en bénéficier, espérons-le.


19
Il y a un excellent post à overeacted qui explique pourquoi cela fonctionne de manière excessive.io/how-does-react-tell-a-class-from-a-function
Eric Kigathi

1
Résumé de l'article: Faire la distinction entre une classe et une fonction dans le navigateur n'est en fait pas complètement trivial ... "La solution actuelle est vraiment simple, mais [je vais sur] une énorme tangente pour expliquer pourquoi React a fini avec cette solution. .. "bla, bla, bla, ... ->" Si vous n'étendez pas React.Component, React ne trouvera pas isReactComponent sur le prototype et ne traitera pas le composant comme une classe. "
spinkus

Génial. J'étais confronté au problème similaire et votre solution a résolu le problème. Mais ma syntaxe était import React, { Component } from 'react'; class extends Component. Je ne pouvais pas comprendre comment cela résolvait le problème en remplaçant Componentpar React.Component. L'importation est-elle importante?
Arun Ramachandran il y a

70

Pour moi, c'était parce que j'avais oublié d'utiliser le newmot - clé lors de la configuration de l'état animé.

par exemple:

fadeAnim: Animated.Value(0),

à

fadeAnim: new Animated.Value(0),

le réparerait.


1
Cela a résolu mon problème, j'utilisais un cas d'utilisation différent, pas l'animation, mais après avoir utilisé le nouveau mot-clé, je l'ai résolu. Merci
Olivier JM

4
J'ai passé 4 heures 44 minutes et 4 secondes à essayer de savoir ce qui s'était passé. Tu es Dieu.
Satheeshwaran

Ouais, c'était moi aussi. Je vous remercie!
James Cushing

64

tl; dr

Si vous utilisez React Router v4, vérifiez votre <Route/>composant si vous utilisez bien le componentprop pour passer votre composant React basé sur la classe!

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

Explication

J'ai eu cette erreur car j'utilisais React Router v4 et j'ai accidentellement utilisé l' renderaccessoire au lieu de componentcelui du <Route/>composant pour passer mon composant qui était une classe. C'était un problème, car renderattend (appelle) une fonction, tandis que componentc'est celle qui fonctionnera sur les composants React.

Donc dans ce code:

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

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

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

C'est dommage qu'ils ne le vérifient pas et donnent une erreur utilisable pour une telle erreur facile à attraper.


47

M'est arrivé parce que j'ai utilisé

PropTypes.arrayOf(SomeClass)

au lieu de

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))


Merci, la mauvaise définition de PropTypes était le problème dans mon cas.
Vasiliy

cela a résolu mon problème! était PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,au lieu de PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Doug

Merci, je me demandais vraiment depuis longtemps ce qui n'allait pas là-bas!
Got The Fever Media

14

Vous avez une export defaultdéclaration en double . Le premier est remplacé par le second qui est en fait une fonction.


Bonne prise! J'ai laissé la valeur par défaut devant GoogleApiComponent et j'obtiens toujours la même erreur. Sinon, la suppression de toutes les valeurs par défaut me donne une erreur de "jeton inattendu" dans mon terminal sur GoogleApiComponent.
Mike Fleming

14

Pour moi, c'était ComponentName.prototypeau lieu de ComponentName.propTypes. auto suggéré par PhpstormIDE. J'espère que cela aidera quelqu'un.


14

J'ai rencontré le même problème, cela s'est produit parce que ma ES6classe de composants ne s'étendait pas React.Component.


8

La plupart du temps, ces problèmes se produisent lorsque vous ne parvenez pas à étendre le composant de react:

import React, {Component} from 'react'

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

7

Pour moi, c'était parce que j'ai utilisé un prototype au lieu de propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

ça devrait être

MyComponent.propTypes = {

};

Exactement le même cas pour moi. Je vous remercie!
Tekson le

6
Post.proptypes = {

}

à

Post.propTypes = {

}

quelqu'un devrait commenter comment surveiller une telle erreur d'une manière très précise.


1
Il est préférable d'expliquer votre solution / réponse avec des informations détaillées.
Dharmang

Yaah ça arrive, Bravo!
Mbanda

3

Il semble qu'il n'y ait pas de cas unique lorsque cette erreur apparaît.

Cela m'est arrivé quand je n'ai pas déclaré le constructeur dans un 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>;
    }
}

3

Deux choses que vous pouvez vérifier sont,

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Assurez-vous que vous étendez React.Component
  • Utilisez propTypes au lieu de prototype (selon IDE intellisense)

devrait être Slider.propTypes: {}
David Casanellas

2

Il s'agit d'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 importun composant spécifique (peu importe s'il provient 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. Par conséquent, ça casse. Voici un exemple courant:

imports

...code...

et puis quelque part dans ton code

<Image {..some props} />

Si vous avez oublié d'importer le composant, <Image />le compilateur ne se plaindra pas comme il le fait pour les autres importations, mais se cassera lorsqu'il atteindra votre code.


1

Pour moi, c'était parce que j'avais accidentellement supprimé ma renderméthode!

J'avais une classe avec une componentWillReceivePropsméthode dont je n'avais plus besoin, précédant immédiatement une renderméthode courte . Dans ma hâte de le retirer, j'ai également supprimé accidentellement toute la renderméthode.

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


1

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

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

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

correctement:

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

ou

const foo = ...
export default foo

1

Pour moi, cela s'est produit parce que je n'ai pas correctement enveloppé ma fonction de connexion et que j'ai essayé d'exporter deux composants par défaut


1

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

J'ai rencontré une erreur dans cet extrait:

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

@inject ("counter")
@Observer

Après quelques corrections comme l'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 pas, c'est que j'utilisais la mauvaise classe au lieu de l' observerutiliser Observeret au lieu de l' counterStoreutiliser counter. J'ai résolu mon problème de cette façon.


1

Dans le fichier MyComponent.js

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

J'ai mis 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é MyComponentsous le nom myFunction!

Donc, le correctif était:

import {myFunction} from './MyComponent'

1

J'ai vécu cela lors de l'écriture d'une instruction d'importation incorrecte lors de l'importation d'une fonction plutôt que d'une classe. Si removeMaterialest une fonction dans un autre module:

Droite:

import { removeMaterial } from './ClaimForm';

Faux:

import removeMaterial from './ClaimForm';

1

J'ai reçu cette erreur en faisant une petite erreur. Mon erreur exportait la classe en tant que fonction plutôt qu'en tant que classe. Au bas de mon fichier de classe, j'avais:

export default InputField();

quand cela aurait dû être:

export default InputField;

0

J'ai également rencontré cela, il est possible que vous ayez une erreur javascript à l'intérieur de votre composant react. Assurez-vous que si vous utilisez une dépendance, vous utilisez l' newopérateur sur la classe pour instancier la nouvelle instance. Une erreur jettera si

this.classInstance = Class({})

utilisez plutôt

this.classInstance = new Class({})

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

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

c'est le cadeau que je crois.


0

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


0

Dans mon cas, j'ai écrit commentà la place de Componentpar 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 vraiment déroutant. J'espère que cela vous sera utile.


0

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

Un autre rapport ici: cela n'a pas fonctionné comme 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 un certain temps pour le retrouver.


0

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

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

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Mais celui-ci a bien fonctionné:

export default connect(mapStateToProps, mapDispatchToProps)(Home)

0

Cela s'est produit lorsque j'ai accidentellement nommé ma renderfonction 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 était simplement dû au fait que ma classe n'avait pas de renderméthode appropriée .


0

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

Correct :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Mauvais et bug :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)

-1

Pour moi, c'était une mauvaise importation d'un réducteur dans le rootReducer.js. J'ai importé un conteneur au lieu d'un fichier réducteur.

Exemple

import settings from './pages/Settings';

Mais bien sûr que ça devrait être

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

Où le répertoire de paramètres contient les fichiers suivants actions.js, index.js, reducer.js.

Pour le vérifier, vous pouvez enregistrer les réducteurs arg de la fonction assertReducerShape () à partir du redux / es / redux.js.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.