Ottenere "Impossibile chiamare una classe come funzione" nel mio progetto React


130

Sto cercando di aggiungere un componente della mappa React al mio progetto ma ho riscontrato un errore. Sto usando il post sul blog di Fullstack React come riferimento. Ho rintracciato dove l'errore viene generato nella riga 83 di google_map.js:

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

Ecco il mio componente della mappa finora. La pagina si carica bene (senza una mappa) quando commento le righe 58-60, le ultime tre righe. modifica: ho apportato le modifiche suggerite da @Dmitriy Nevzorov e mi dà ancora lo stesso errore.

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)

Ed ecco dove questo componente della mappa viene instradato 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'))

2
Hai due export defaults, e sarebbe new GoogleAPIComponent()non GoogleAPIComponent()?
gcampbell,

Ho rimosso una delle impostazioni predefinite e ho provato il tuo suggerimento. Sembra che in realtà stia parlando con Google Maps ora, il che è buono, ma prima che la pagina possa caricarsi genera un altro errore criptico: Locations.js: 58 Uncaught TypeError: (valore intermedio) non è una funzione ". Qualche idea?
Mike Fleming,

1
Cosa succede se si rimuove il (LocationContainer)?
gcampbell,

Grazie, penso di averlo capito! Strano, è così che l'hanno scritto sul loro post sul blog. Sempre ricevendo alcuni altri errori da Google Maps, li inserirò qui: "GoogleMap: apiKey è obsoleto, utilizzare invece bootstrapURLKeys = {{key: YOUR_API_KEY}}. google_map.js: 689 GoogleMap: centro o default È necessario definire la proprietà del centro google_map.js: 699 GoogleMap: zoom o impostazione predefinita È necessario definire la non conformità google_map.js: 704 '
Mike Fleming,

1
Non sono sicuro degli altri errori, ma potresti provare questo per correggere il primo:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

Risposte:


207

Per me è successo quando mi sono dimenticato di scrivere extends React.Componentalla fine. So che non è esattamente quello che avevi, ma altri che leggono questa risposta possono trarne beneficio, si spera.


19
C'è un ottimo post su overreacted che spiega perché funziona overreacted.io/how-does-react-tell-a-class-from-a-function
Eric Kigathi,

1
Riepilogo del post: Distinguere tra una classe e una funzione nel browser non è in realtà del tutto banale ... "La soluzione reale è davvero semplice, ma [sto andando su] una grande tangente per spiegare perché React ha finito con questa soluzione. .. "blah, blah, blah, ... ->" Se non estendi React.Component, React non troverà isReactComponent sul prototipo e non tratterà il componente come una classe. "
spinkus,

Grande. Stavo affrontando il problema simile e la tua soluzione ha risolto il problema. Ma la mia sintassi era import React, { Component } from 'react'; class extends Component. Non riuscivo a capire come questo ha risolto il problema sostituendolo Componentcon React.Component. L'importazione è importante?
Arun Ramachandran

70

Per me è stato perché ho dimenticato di usare la newparola chiave durante l'impostazione dello stato animato.

per esempio:

fadeAnim: Animated.Value(0),

per

fadeAnim: new Animated.Value(0),

lo aggiusterò.


1
Questo ha risolto il mio problema, stavo usando un altro caso d'uso non animato ma dopo aver risolto il problema con la nuova parola chiave. Grazie
Olivier JM,

4
Ho trascorso 4 ore e 44 minuti e 4 secondi cercando di sapere cosa è successo. Tu sei dio.
Satheeshwaran,

Sì, ero anche io. Grazie!
James Cushing,

64

tl; dr

Se usi React Router v4 controlla il tuo <Route/>componente se effettivamente usi l' componentelica per passare il tuo componente React basato sulla classe!

Più in generale: se la tua classe sembra a posto, controlla se il codice che la chiama non cerca di usarla come funzione.

Spiegazione

Ho avuto questo errore perché stavo usando React Router v4 e ho usato accidentalmente l' renderelica invece di componentquella nel <Route/>componente per passare il mio componente che era una classe. Questo è stato un problema, perché si renderaspetta (chiama) una funzione, mentre componentè quella che funzionerà sui componenti di React.

Quindi in questo codice:

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

La riga contenente il <Route/>componente avrebbe dovuto essere scritta in questo modo:

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

È un peccato che non lo controllino e diano un errore utilizzabile per un errore del genere e facile da rilevare.


47

Mi è successo perché l'ho usato

PropTypes.arrayOf(SomeClass)

invece di

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))


Grazie, la definizione errata di PropTypes era il problema nel mio caso.
Vasiliy,

questo ha risolto il mio problema! era PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,invece di PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Doug

Grazie, mi chiedevo davvero da molto tempo che cosa non andava lì!
Ho ricevuto The Fever Media il

14

Hai una export defaultdichiarazione duplicata . Il primo viene sovrascritto dal secondo, che in realtà è una funzione.


Buona pesca! Ho lasciato il valore predefinito davanti a GoogleApiComponent e continuo a ricevere lo stesso errore. In alternativa, la rimozione di tutti i valori predefiniti mi dà un errore "token imprevisto" nel mio terminale su GoogleApiComponent.
Mike Fleming,

14

Per me è stato ComponentName.prototypeinvece di ComponentName.propTypes. auto suggerito da PhpstormIDE. Spero che possa aiutare qualcuno.


14

Ho riscontrato lo stesso problema, si è verificato perché la mia ES6classe di componenti non si stava estendendo React.Component.


8

Per lo più questi problemi si verificano quando si perde l'estensione del componente da reagire:

import React, {Component} from 'react'

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

7

Per me è stato perché ho usato il prototipo anziché i propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

dovrebbe essere

MyComponent.propTypes = {

};

Lo stesso caso per me. Grazie!
Tekson il

6
Post.proptypes = {

}

per

Post.propTypes = {

}

qualcuno dovrebbe commentare come monitorare tale errore in modo molto preciso.


1
È meglio spiegare la soluzione / risposta con alcune informazioni dettagliate.
Dharmang,

Yaah succede, Bravo!
Mbanda,

3

Sembra che non ci siano casi singoli quando appare questo errore.

Mi è successo quando non ho dichiarato costruttore in componente statefull.

class MyComponent extends Component {

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

invece di

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

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

3

Due cose che puoi controllare sono:

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Assicurati di estendere React.Component
  • Usa propTypes invece del prototipo (secondo IDE intellisense)

dovrebbe essere Slider.propTypes: {}
David Casanellas il

2

Questo è un problema generale e non appare in un singolo caso. Ma il problema comune in tutti i casi è che ti dimentichi di importun componente specifico (non importa se proviene da una libreria che hai installato o da un componente personalizzato che hai creato):

import {SomeClass} from 'some-library'

Quando lo usi in seguito, senza importarlo, il compilatore pensa che sia una funzione. Pertanto, si rompe. Questo è un esempio comune:

imports

...code...

e poi da qualche parte all'interno del tuo codice

<Image {..some props} />

Se hai dimenticato di importare il componente, <Image />il compilatore non si lamenterà come fa per altre importazioni, ma si interromperà quando raggiungerà il tuo codice.


1

Per me, è stato perché avevo accidentalmente cancellato il mio rendermetodo!

Avevo una lezione con un componentWillReceivePropsmetodo che non mi serviva più, che precedeva immediatamente un rendermetodo breve . Nella fretta di rimuoverlo, ho rimosso accidentalmente anche l'intero rendermetodo.

Questo è stato un DOLORE da rintracciare, poiché stavo ottenendo errori della console che puntavano ai commenti in file completamente irrilevanti come "fonte" del problema.


1

Ho avuto un problema simile, stavo chiamando il metodo di rendering in modo errato

Ha dato un errore:

render = () => {
    ...
}

invece di

corretta:

render(){
    ...
}

1

L'ho avuto quando l'ho fatto:

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

correttamente:

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

o

const foo = ...
export default foo

1

Per me è successo perché non ho avvolto correttamente la mia funzione di connessione e ho provato a esportare due componenti predefiniti


1

Ho riscontrato questo errore quando ho importato la classe sbagliata e ho fatto riferimento a un negozio sbagliato durante l'utilizzo di mobx in React-native.

Ho riscontrato un errore in questo frammento:

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

@inject ("counter")
@Observer

Dopo alcune correzioni come nello snippet di seguito. Ho risolto il mio problema in questo modo.

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

@inject("counterStore")
@observer

Ciò che era effettivamente sbagliato, stavo usando la classe sbagliata invece di observerusare Observere invece di counterStoreusare counter. Ho risolto il mio problema in questo modo.


1

Nel file MyComponent.js

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

Ho inserito alcune funzioni relative a quel componente:

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

export myFunction() {
...
}

e poi in un altro file importato quella funzione:

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

Riesci a individuare il problema?

Ho dimenticato le parentesi graffe e importato MyComponentcon il nome myFunction!

Quindi, la correzione era:

import {myFunction} from './MyComponent'

1

Ho riscontrato questo errore durante la scrittura errata di una dichiarazione di importazione durante l'importazione di una funzione anziché di una classe. Se removeMaterialè una funzione in un altro modulo:

Destra:

import { removeMaterial } from './ClaimForm';

Sbagliato:

import removeMaterial from './ClaimForm';

1

Ho ricevuto questo errore commettendo un piccolo errore. Il mio errore era l'esportazione della classe come funzione anziché come classe. In fondo al mio file di classe avevo:

export default InputField();

quando avrebbe dovuto essere:

export default InputField;

0

Ho anche incontrato questo, è possibile che tu abbia un errore javascript all'interno del tuo componente di reazione. Assicurarsi che se si utilizza una dipendenza si sta utilizzando l' newoperatore sulla classe per creare un'istanza della nuova istanza. L'errore genererà if

this.classInstance = Class({})

invece usa

this.classInstance = new Class({})

vedrai nella catena degli errori nel browser

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

questo è l'omaggio che credo.


0

Prova a fermare il tuo HMR e premi di npm startnuovo per ricostruire il tuo progetto.
Questo, fatto scomparire l'errore, non so perché.


0

Nel mio caso ho scritto commental posto di Componentper errore

Ho appena scritto questo.

import React, { Component } from 'react';

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

Invece di questo.

import React, { Component } from 'react';

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

non è un grosso problema, ma per un principiante come me è davvero confuso. Spero che questo ti sarà d'aiuto.


0

Nel mio caso, usando JSX un componente padre stava chiamando altri componenti senza "<>"

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

fix

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

0

Un altro rapporto qui: non ha funzionato come ho esportato:

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

invece di

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

Nota la posizione delle parentesi. Entrambi sono corretti e non verranno catturati da una linter o più carina o qualcosa di simile. Mi ci è voluto un po 'per rintracciarlo.


0

Nel mio caso, ho accidentalmente inserito il nome del componente ( Home) come primo argomento che connectfunzionava mentre doveva essere alla fine. duh.

Questo sicuramente mi ha dato l'errore:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Ma questo ha funzionato - sicuramente - bene:

export default connect(mapStateToProps, mapDispatchToProps)(Home)

0

Ciò si è verificato quando ho rendererroneamente chiamato la mia funzione in modo errato:

import React from 'react';

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

La mia istanza di questo errore è stata semplicemente causata perché la mia classe non aveva un rendermetodo adeguato .


0

In realtà tutto il problema redux connect. soluzioni:

Corretto :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Errato e bug :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)

-1

Per me è stata un'importazione errata di un riduttore nel rootReducer.js. Ho importato un contenitore invece del file riduttore.

Esempio

import settings from './pages/Settings';

Ma sicuramente dovrebbe essere

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

Dove la directory delle impostazioni contiene i seguenti file actions.js, index.js, riduzioneer.js.

Per verificarlo è possibile registrare i riduttori arg della funzione assertReducerShape () da redux / es / redux.js.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.