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'))
Mike Fleming
źródło
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ć.

programista
źródło
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.

William Park
źródło
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.

totymedli
źródło
47

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

PropTypes.arrayOf(SomeClass)

zamiast

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))

Dan Balaban
źródło
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ą.

Dmitriy Nevzorov
źródło
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.

codersaif
źródło
14

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

Dżem
źródło
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();     
    }
}
jeff ayan
źródło
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 = {

};
Onengiye Richard
źródło
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.

Mbanda
źródło
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>;
    }
}
Pavel Kozlov
źródło
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)
Dipen Dedania
źródło
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.

Tim G. Pegas
źródło
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.

Alex McMillan
źródło
1

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

Wystąpił błąd:

render = () => {
    ...
}

zamiast

poprawny:

render(){
    ...
}
Emile Esterhuizen
źródło
1

Miałem to, kiedy to zrobiłem:

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

prawidłowo:

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

lub

const foo = ...
export default foo
Jeka Yaroshenko
źródło
1

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

Dmitriy
źródło
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.

badarshahzad
źródło
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'
Michaił Vasin
źródło
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';
shacker
źródło
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;
airvine
źródło
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ę.

mibbit
źródło
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.

Alexander Gorelik
źródło
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.

Uddesh_jain
źródło
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 />} />
Alan
źródło
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.

Sebastijan Dumančić
źródło
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)
straszny
źródło
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.

Bryan Bor
źródło
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)
Batuhan Orhan
źródło
-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.

Oleg Shishkov
źródło