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'))
Mike Fleming
la source
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.

programmeur
la source
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.

William Park
la source
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.

totymedli
la source
47

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

PropTypes.arrayOf(SomeClass)

au lieu de

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))

Dan Balaban
la source
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.

Dmitriy Nevzorov
la source
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.

codersaif
la source
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.

Confiture
la source
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();     
    }
}
Jeff Ayan
la source
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 = {

};
Onengiye Richard
la source
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.

Mbanda
la source
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>;
    }
}
Pavel Kozlov
la source
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)
Dipen Dedania
la source
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.

Tim G. Pegas
la source
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.

Alex McMillan
la source
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(){
    ...
}
Emile Esterhuizen
la source
1

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

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

correctement:

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

ou

const foo = ...
export default foo
Jeka Yaroshenko
la source
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

Dmitriy
la source
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.

Badarshahzad
la source
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'
Mikhail Vasin
la source
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';
shacker
la source
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;
airvine
la source
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.

mibbit
la source
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.

Alexandre Gorelik
la source
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.

Uddesh_jain
la source
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 />} />
Alan
la source
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.

Sebastijan Dumančić
la source
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)
effrayant
la source
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 .

Bryan Bor
la source
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)
Batuhan Orhan
la source
-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.

Oleg Shishkov
la source