Otrzymanie „Nie można wywołać klasy jako funkcji” w moim projekcie React


129

Próbuję dodać komponent mapy React do mojego projektu, ale pojawia się błąd. Używam posta na blogu Fullstack React jako odniesienia. Wyśledziłem, gdzie pojawia się błąd w linii google_map.js 83:

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

Oto mój dotychczasowy komponent mapy. Strona ładuje się dobrze (bez mapy), kiedy komentuję wiersze 58-60, ostatnie trzy wiersze. edycja: wprowadziłem zmiany, które zasugerował @Dmitriy Nevzorov i nadal daje mi to ten sam błąd.

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)

A oto, gdzie ten komponent mapy jest kierowany w 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
Masz dwa export default, a czy new GoogleAPIComponent()nie GoogleAPIComponent()?
gcampbell

Usunąłem jedno z ustawień domyślnych i wypróbowałem twoją sugestię. Wygląda na to, że faktycznie komunikuje się teraz z Mapami Google, co jest dobre, ale zanim strona może się załadować, wyświetla kolejny tajemniczy błąd: Locations.js: 58 Uncaught TypeError: (wartość pośrednia) nie jest funkcją ". Jakieś pomysły?
Mike Fleming

1
A co jeśli usuniesz (LocationContainer)?
gcampbell

Dzięki, myślę, że dostałem to! Dziwne, tak to napisali na swoim blogu. Nadal otrzymuję kilka innych błędów z Map Google, wstawię je tutaj: „GoogleMap: apiKey jest przestarzały, użyj zamiast tego bootstrapURLKeys = {{key: YOUR_API_KEY}}. google_map.js: 689 GoogleMap: center lub defaultCenterproperty muszą być zdefiniowane google_map.js: 699 GoogleMap: zoom lub defaultZoomproperty muszą być zdefiniowane google_map.js: 704 '
Mike Fleming

1
Nie jestem pewien co do innych błędów, ale możesz spróbować naprawić ten pierwszy:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

Odpowiedzi:


206

U mnie stało się to, kiedy na końcu zapomniałem napisać extends React.Component. Wiem, że to nie jest dokładnie to, co TY miałeś, ale miejmy nadzieję, że inni czytający tę odpowiedź mogą na tym skorzystać.


19
W overreacted jest świetny post, który wyjaśnia, dlaczego to działa overreacted.io/how-does-react-tell-a-class-from-a-function
Eric Kigathi,

1
Podsumowanie posta: Rozróżnienie między klasą a funkcją w przeglądarce nie jest właściwie trywialne ... ”Właściwe rozwiązanie jest naprawdę proste, ale [mam] ogromną styczność, aby wyjaśnić, dlaczego React znalazł to rozwiązanie. .. "bla, bla, bla, ... ->" Jeśli nie rozszerzysz React.Component, React nie znajdzie isReactComponent w prototypie i nie będzie traktował komponentu jako klasy. "
spinkus

70

Dla mnie to dlatego, że zapomniałem użyć newsłowa kluczowego podczas konfigurowania stanu animacji.

na przykład:

fadeAnim: Animated.Value(0),

do

fadeAnim: new Animated.Value(0),

naprawi to.


1
To rozwiązało mój problem, użyłem innego przypadku użycia nie animowanego, ale po użyciu nowego słowa kluczowego rozwiązałem go. Dziękuję
Olivier JM

3
Spędziłem 4 godziny 44 minuty i 4 sekundy, próbując dowiedzieć się, co się stało. Jesteś Bogiem.
Satheeshwaran

Tak, to też byłem ja. Dziękuję Ci!
James Cushing,

64

tl; dr

Jeśli używasz React Router v4, sprawdź swój <Route/>komponent, jeśli rzeczywiście używaszcomponent aby przekazać komponent React oparty na klasie!

Mówiąc bardziej ogólnie: jeśli Twoja klasa wydaje się w porządku, sprawdź, czy kod, który ją wywołuje, nie próbuje jej użyć jako funkcji.

Wyjaśnienie

Otrzymałem ten błąd, ponieważ używałem React Router v4 i przypadkowo użyłem właściwości renderzamiast tego componentw <Route/>komponencie, aby przekazać mój komponent, który był klasą. To był problem, ponieważ renderoczekuje (wywołuje) funkcję, podczas gdy componentjest tą, która będzie działać na komponentach React.

Więc w tym kodzie:

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

Wiersz zawierający <Route/>komponent powinien być napisany w ten sposób:

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

Szkoda, że ​​nie sprawdzają tego i dają użyteczny błąd za tak łatwy do wyłapania błąd.


47

Przydarzyło mi się, ponieważ użyłem

PropTypes.arrayOf(SomeClass)

zamiast

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))


Dzięki, w moim przypadku problemem była zła definicja PropTypes.
Wasilij

to rozwiązało mój problem! był PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,zamiast PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Doug

Dzięki, długo się zastanawiałem, co się tam dzieje!
Got The Fever Media

14

Masz zduplikowaną export defaultdeklarację. Pierwsza jest zastępowana przez drugą, która w rzeczywistości jest funkcją.


Dobry chwyt! Zostawiłem wartość domyślną przed GoogleApiComponent i nadal otrzymuję ten sam błąd. Ewentualnie usunięcie wszystkich ustawień domyślnych powoduje wyświetlenie błędu „nieoczekiwanego tokena” w moim terminalu w GoogleApiComponent.
Mike Fleming

14

Dla mnie to było ComponentName.prototypezamiast ComponentName.propTypes. auto sugerowane przez PhpstormIDE. Mam nadzieję, że to komuś pomoże.


14

Wystąpił ten sam problem, ponieważ moja ES6klasa komponentów nie rozszerzała się React.Component.


8

Przeważnie te problemy występują, gdy przegapisz rozszerzenie komponentu z reaguj:

import React, {Component} from 'react'

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

7

Dla mnie to dlatego, że użyłem prototypu zamiast propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

tak powinno być

MyComponent.propTypes = {

};

Dokładnie to samo dotyczy mnie. Dziękuję Ci!
Tekson

6
Post.proptypes = {

}

do

Post.propTypes = {

}

ktoś powinien wypowiedzieć się jak bardzo dokładnie monitorować taki błąd.


1
Lepiej jest wyjaśnić swoje rozwiązanie / odpowiedź, podając szczegółowe informacje.
Dharmang

Tak, to się dzieje, Bravo!
Mbanda

3

Wygląda na to, że nie ma jednego przypadku, gdy pojawia się ten błąd.

Zdarzyło mi się, gdy nie zadeklarowałem konstruktora w komponencie statefull.

class MyComponent extends Component {

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

zamiast

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

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

3

Dwie rzeczy, które możesz sprawdzić, to:

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Upewnij się, że rozszerzasz React.Component
  • Użyj propTypes zamiast prototypu (zgodnie z inteligencją IDE)

powinno być Slider.propTypes: {}
David Casanellas,

2

Jest to problem ogólny i nie występuje w żadnym przypadku. Jednak częstym problemem we wszystkich przypadkach jest to, że zapominasz importo konkretnym komponencie (nie ma znaczenia, czy pochodzi on z zainstalowanej biblioteki, czy z utworzonego niestandardowego komponentu):

import {SomeClass} from 'some-library'

Kiedy używasz go później, bez importowania, kompilator uważa, że ​​jest to funkcja. Dlatego pęka. To jest typowy przykład:

imports

...code...

a potem gdzieś w kodzie

<Image {..some props} />

Jeśli zapomniałeś zaimportować komponentu, <Image />kompilator nie będzie narzekał, tak jak w przypadku innych importów, ale zepsuje się, gdy dotrze do twojego kodu.


1

Dla mnie to dlatego, że przypadkowo usunąłem swoją rendermetodę!

Miałem klasę z componentWillReceivePropsmetodą, której już nie potrzebowałem, bezpośrednio poprzedzającą krótką rendermetodę. W pośpiechu usuwając ją, przypadkowo usunąłem również całą rendermetodę.

To był BÓL do wyśledzenia, ponieważ otrzymywałem błędy konsoli wskazujące na komentarze w zupełnie nieistotnych plikach jako „źródło” problemu.


1

Miałem podobny problem, ponieważ nieprawidłowo wywoływałem metodę renderowania

Wystąpił błąd:

render = () => {
    ...
}

zamiast

poprawny:

render(){
    ...
}

1

Miałem to, kiedy to zrobiłem:

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

prawidłowo:

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

lub

const foo = ...
export default foo

1

U mnie stało się tak, ponieważ nie opakowałem poprawnie funkcji connect i próbowałem wyeksportować domyślne dwa komponenty


1

Napotkałem ten błąd, gdy zaimportowałem niewłaściwą klasę i odniosłem się do niewłaściwego sklepu podczas korzystania z mobx w react-native.

Wystąpił błąd w tym fragmencie:

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

@inject ("counter")
@Observer

Po kilku poprawkach jak poniżej fragment. W ten sposób rozwiązałem swój problem.

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

@inject("counterStore")
@observer

Co było właściwie nie tak, zamiast tego observerużyłem złej klasy , Observera zamiast tego counterStoreużyłem counter. W ten sposób rozwiązałem swój problem.


1

W pliku MyComponent.js

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

Dodałem funkcję związaną z tym komponentem:

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

export myFunction() {
...
}

a następnie w innym pliku zaimportowano tę funkcję:

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

Czy potrafisz dostrzec problem?

Zapomniałem o szelkach kręconych i importowałem je MyComponentpod nazwą myFunction!

Tak więc poprawka była taka:

import {myFunction} from './MyComponent'

1

Doświadczyłem tego, pisząc instrukcję importu nieprawidłowo podczas importowania funkcji, a nie klasy. Jeśli removeMaterialjest funkcją w innym module:

Dobrze:

import { removeMaterial } from './ClaimForm';

Źle:

import removeMaterial from './ClaimForm';

1

Otrzymałem ten błąd, popełniając mały błąd. Mój błąd polegał na wyeksportowaniu klasy jako funkcji, a nie jako klasy. Na dole mojego pliku klasy miałem:

export default InputField();

kiedy powinno być:

export default InputField;

0

Też napotkałem to, możliwe, że masz błąd javascript w komponencie reagowania. Upewnij się, że jeśli używasz zależności, używasz newoperatora na klasie do utworzenia wystąpienia nowej instancji. Błąd wyrzuci if

this.classInstance = Class({})

zamiast tego użyj

this.classInstance = new Class({})

zobaczysz w łańcuchu błędów w przeglądarce

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

to jest gratka, którą wierzę.


0

Spróbuj zatrzymać HMR i uderzyć npm start ponownie, aby odbudować swój projekt.
To spowodowało zniknięcie błędu, nie wiem dlaczego.


0

W moim przypadku napisałem commentw miejsce Componentprzez pomyłkę

Właśnie to napisałem.

import React, { Component } from 'react';

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

Zamiast tego.

import React, { Component } from 'react';

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

to nic wielkiego, ale dla początkującego takiego jak ja jest to naprawdę zagmatwane. Mam nadzieję, że to będzie pomocne.


0

W moim przypadku użycie JSX komponentu nadrzędnego wywoływało inne komponenty bez „<>”

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

naprawić

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

0

Kolejny raport tutaj: Nie zadziałał, gdy wyeksportowałem:

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

zamiast

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

Zwróć uwagę na położenie nawiasów. Obie są poprawne i nie zostaną złapane ani przez linter, ani przez ładniejszą, ani przez coś podobnego. Zajęło mi trochę czasu, zanim to wyśledziłem.


0

W moim przypadku przypadkowo umieściłem nazwę komponentu ( Home) jako pierwszy argument connectfunkcji, podczas gdy miała znajdować się na końcu. duh.

Ten - na pewno - dał mi błąd:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Ale ten działał - z pewnością - dobrze:

export default connect(mapStateToProps, mapDispatchToProps)(Home)

0

Zdarzyło się to, gdy przypadkowo nazwałem swoją renderfunkcję nieprawidłowo:

import React from 'react';

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

Moje wystąpienie tego błędu było po prostu spowodowane tym, że moja klasa nie miała odpowiedniej rendermetody.


0

Właściwie cały problem redux connect. rozwiązania:

Poprawnie :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Błędne & błąd :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)

-1

Dla mnie był to zły import reduktora w rootReducer.js. Zaimportowałem kontener zamiast pliku reduktora.

Przykład

import settings from './pages/Settings';

Ale na pewno tak powinno być

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

Gdzie katalog ustawień zawiera następujące pliki action.js, index.js, reduktor.js.

Aby to sprawdzić, możesz zarejestrować argument redukujący funkcji assertReducerShape () z redux / es / redux.js.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.