Obtendo “Não é possível chamar uma classe como uma função” no meu projeto React

130

Estou tentando adicionar um componente do mapa React ao meu projeto, mas ocorreu um erro. Estou usando Fullstack Reagir do post como uma referência. Eu localizei onde o erro é gerado na linha 83 do google_map.js:

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

Aqui está o meu componente de mapa até agora. A página carrega muito bem (sem mapa) quando eu comento as linhas 58 a 60, as últimas três linhas. edit: Fiz as alterações que @Dmitriy Nevzorov sugeriu e ainda me dá o mesmo erro.

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)

E aqui é onde esse componente do mapa é roteado no 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
fonte
2
Você tem duas export defaults, e seria new GoogleAPIComponent()não GoogleAPIComponent()?
Gcampbell
Eu removi um dos padrões e tentei sua sugestão. Parece que ele está realmente conversando com o Google Maps agora, o que é bom, mas antes que a página possa ser carregada, gera outro erro enigmático: Locations.js: 58 Tipo não detectadoErro: (valor intermediário) não é uma função ". Alguma idéia?
Mike Fleming
1
E se você remover o (LocationContainer)?
Gcampbell
Obrigado, acho que entendi! Estranho, é assim que eles escrevem em suas postagens no blog. Ainda com alguns outros erros do Google Maps, os colocarei aqui: 'GoogleMap: apiKey está obsoleto, use bootstrapURLKeys = {{key: YOUR_API_KEY}}. google_map.js: 689 GoogleMap: center ou defaultCenterproperty deve ser definido google_map.js: 699 GoogleMap: zoom ou defaultZoomproperty deve ser definido google_map.js: 704 '
Mike Fleming
1
Eu não tenho certeza sobre os outros erros, mas você pode tentar este para corrigir o primeiro:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

Respostas:

207

Para mim, aconteceu quando eu esqueci de escrever extends React.Componentno final. Sei que não é exatamente o que VOCÊ teve, mas espero que outros que estejam lendo esta resposta possam se beneficiar disso.

programador
fonte
19
Há grande post em exagerou que explica por que isso funciona overreacted.io/how-does-react-tell-a-class-from-a-function
Eric Kigathi
1
Resumo da postagem: A distinção entre uma classe e uma função no navegador não é completamente trivial ... "A solução real é realmente simples, mas [estou indo] uma enorme tangente para explicar por que o React acabou com esta solução. .. "blá, blá, blá, ... ->" Se você não estender o React.Component, o React não encontrará isReactComponent no protótipo e não tratará o componente como uma classe. "
spinkus 22/07
Ótimo. Eu estava enfrentando o problema semelhante e sua solução corrigiu o problema. Mas minha sintaxe era import React, { Component } from 'react'; class extends Component. Não consegui entender como isso resolveu o problema substituindo Componentpor React.Component. A importação importa?
Arun Ramachandran
70

Para mim, foi porque esqueci de usar a newpalavra - chave ao configurar o estado Animated.

por exemplo:

fadeAnim: Animated.Value(0),

para

fadeAnim: new Animated.Value(0),

iria consertar isso.

William Park
fonte
1
Isso resolveu meu problema, eu estava usando um caso de uso diferente, não o animado, mas depois de usar a nova palavra-chave resolvi-o. Obrigado
Olivier JM
4
Passamos 4 horas 44 minutos e 4 segundos tentando saber o que aconteceu. Você é Deus.
Satheeshwaran
Sim, isso era eu também. Obrigado!
James Cushing
64

tl; dr

Se você usa o React Router v4, verifique seu <Route/>componente se realmente usa ocomponent prop para passar seu componente React baseado em classe!

De maneira mais geral: se sua classe parecer correta, verifique se o código que a chama não tenta usá-la como uma função.

Explicação

Eu recebi esse erro porque estava usando o React Router v4 e acidentalmente usei o renderprop em vez componentdaquele no <Route/>componente para passar meu componente que era uma classe. Isso foi um problema, porque renderespera (chama) uma função, enquantocomponent é a única que funcionará nos componentes do React.

Portanto, neste código:

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

A linha que contém o <Route/>componente deveria ter sido escrita assim:

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

É uma pena que eles não verifiquem e dêem um erro utilizável para tal e fácil de detectar erros.

totymedli
fonte
47

Aconteceu comigo porque eu costumava

PropTypes.arrayOf(SomeClass)

ao invés de

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))

Dan Balaban
fonte
Obrigado, definição errada de PropTypes foi o problema no meu caso.
Vasiliy
isso resolveu meu problema! foi em PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,vez de PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Doug
Obrigado, fiquei realmente pensando por um longo tempo o que estava errado lá!
Got The Fever Media
14

Você duplicou a export defaultdeclaração. O primeiro é substituído pelo segundo, que na verdade é uma função.

Dmitriy Nevzorov
fonte
Boa pegada! Deixei o padrão na frente do GoogleApiComponent e ainda recebo o mesmo erro. Como alternativa, a remoção de todos os padrões gera um erro de "token inesperado" no meu terminal no GoogleApiComponent.
21816 Mike Fleming
14

Para mim, foi em ComponentName.prototypevez de ComponentName.propTypes. auto sugerido pelo PhpstormIDE. Espero que ajude alguém.

codersaif
fonte
14

Tive o mesmo problema, ocorreu porque minha ES6classe de componente não estava sendo estendida React.Component.

Geléia
fonte
8

Esses problemas ocorrem principalmente quando você deixa de estender o Component ao reagir:

import React, {Component} from 'react'

export default class TimePicker extends Component {
    render() {
        return();     
    }
}
jeff ayan
fonte
7

Para mim, foi porque usei protótipo em vez de propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

deveria ser

MyComponent.propTypes = {

};
Onengiye Richard
fonte
Exato mesmo caso para mim. Obrigado!
Tekson 18/04
6
Post.proptypes = {

}

para

Post.propTypes = {

}

alguém deve comentar sobre como monitorar esse erro de uma maneira muito precisa.

Mbanda
fonte
1
É melhor explicar sua solução / resposta com algumas informações detalhadas.
Dharmang
Yaah isso acontece, Bravo!
Mbanda 20/08/19
3

Parece que não há um caso único quando esse erro aparece.

Aconteceu comigo quando não declarei construtor no componente statefull.

class MyComponent extends Component {

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

ao invés de

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return <div>Test</div>;
    }
}
Pavel Kozlov
fonte
3

Duas coisas que você pode verificar é:

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Certifique-se de estender React.Component
  • Use propTypes em vez de prototype (conforme IDE intellisense)
Dipen Dedania
fonte
deve ser Slider.propTypes: {}
David Casanellas
2

Esse é um problema geral e não aparece em um único caso. Mas, o problema comum em todos os casos é que você se esquece de importum componente específico (não importa se é de uma biblioteca que você instalou ou de um componente personalizado que você criou):

import {SomeClass} from 'some-library'

Quando você o usa mais tarde, sem importá-lo, o compilador acha que é uma função. Portanto, quebra. Este é um exemplo comum:

imports

...code...

e depois em algum lugar dentro do seu código

<Image {..some props} />

Se você esqueceu de importar o componente <Image />, o compilador não reclamará como ocorre com outras importações, mas será interrompido quando atingir seu código.

Tim G. Pegas
fonte
1

Para mim, foi porque eu excluí acidentalmente meu rendermétodo!

Eu tive uma classe com um componentWillReceivePropsmétodo que não precisava mais, imediatamente precedendo um rendermétodo curto . Na minha pressa em removê-lo, removi acidentalmente todo o rendermétodo também.

Era uma PAIN para rastrear, pois eu estava recebendo erros do console apontando comentários em arquivos completamente irrelevantes como sendo a "fonte" do problema.

Alex McMillan
fonte
1

Eu tive um problema semelhante, estava chamando o método de renderização incorretamente

Deu um erro:

render = () => {
    ...
}

ao invés de

corrigir:

render(){
    ...
}
Emile Esterhuizen
fonte
1

Eu tinha quando o fiz:

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

corretamente:

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

ou

const foo = ...
export default foo
Jeka Yaroshenko
fonte
1

Para mim, aconteceu porque eu não envolvi minha função de conexão corretamente e tentei exportar dois componentes padrão

Dmitriy
fonte
1

Eu enfrentei esse erro quando importei a classe errada e me referi ao armazenamento errado ao usar o mobx no react-native.

Eu enfrentei um erro neste trecho:

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

@inject ("counter")
@Observer

Após algumas correções, como abaixo do snippet. Resolvi meu problema dessa maneira.

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

@inject("counterStore")
@observer

O que estava realmente errado, eu estava usando a classe errada em vez de observerusar Observere em vez de counterStoreusar counter. Resolvi meu problema dessa maneira.

badarshahzad
fonte
1

No arquivo MyComponent.js

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

Eu coloquei alguma função relacionada a esse componente:

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

export myFunction() {
...
}

e depois em outro arquivo importado essa função:

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

Você consegue identificar o problema?

Esqueci o aparelho e importado MyComponentsob o nome myFunction!

Então, a correção foi:

import {myFunction} from './MyComponent'
Mikhail Vasin
fonte
1

Eu experimentei isso ao escrever uma instrução de importação incorreta ao importar uma função, em vez de uma classe. Se removeMaterialé uma função em outro módulo:

Certo:

import { removeMaterial } from './ClaimForm';

Errado:

import removeMaterial from './ClaimForm';
shacker
fonte
1

Eu recebi esse erro cometendo um pequeno erro. Meu erro foi exportar a classe como uma função em vez de como uma classe. Na parte inferior do meu arquivo de classe, eu tinha:

export default InputField();

quando deveria ter sido:

export default InputField;
airvine
fonte
0

Também deparei com isso, é possível que você tenha um erro de javascript dentro do seu componente de reação. Verifique se você está usando uma dependência, se está usando o newoperador na classe para instanciar a nova instância. Erro lançará se

this.classInstance = Class({})

em vez disso, use

this.classInstance = new Class({})

você verá na cadeia de erros no navegador

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

essa é a oferta que eu acredito.

mibbit
fonte
0

Tente parar seu HMR e pressione npm startnovamente para reconstruir seu projeto.
Isso fez o erro desaparecer, não sei por quê.

Alexander Gorelik
fonte
0

No meu caso, eu escrevi commentno lugar de Componentpor engano

Eu acabei de escrever isso.

import React, { Component } from 'react';

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

Em vez disso.

import React, { Component } from 'react';

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

não é grande coisa, mas para um iniciante como eu é realmente confuso. Espero que isso seja útil.

Uddesh_jain
fonte
0

No meu caso, usando JSX, um componente pai estava chamando outros componentes sem o "<>"

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

consertar

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

Outro relatório aqui: não funcionou como eu exportei:

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

ao invés de

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

Observe a posição dos colchetes. Ambos estão corretos e não serão pegos por um linter ou mais bonito ou algo semelhante. Levei um tempo para encontrá-lo.

Sebastijan Dumančić
fonte
0

No meu caso, acidentalmente coloquei o nome do componente ( Home) como o primeiro argumento a connectfuncionar enquanto deveria estar no final. duh.

Este - com certeza - me deu o erro:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Mas este funcionou bem:

export default connect(mapStateToProps, mapDispatchToProps)(Home)
assustador
fonte
0

Isso ocorreu quando acidentalmente nomeei minha renderfunção incorretamente:

import React from 'react';

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

Minha instância desse erro foi causada simplesmente porque minha classe não tinha um rendermétodo adequado .

Bryan Bor
fonte
0

Na verdade, todo o problema de redux conectar. soluções:

Correto :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Erro e erro :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)
Batuhan Orhan
fonte
-1

Para mim, foi uma importação incorreta de um redutor no rootReducer.js. Importei contêiner em vez de arquivo redutor.

Exemplo

import settings from './pages/Settings';

Mas com certeza deve ser

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

Onde o diretório settings contém os seguintes arquivos actions.js, index.js, reducer.js.

Para verificar isso, você pode registrar os redutores arg da função assertReducerShape () no redux / es / redux.js.

Oleg Shishkov
fonte