Obtener "No se puede llamar a una clase como una función" en mi proyecto React


130

Estoy tratando de agregar un componente de mapa React a mi proyecto pero me encuentro con un error. Estoy usando la publicación de blog de Fullstack React como referencia. Rastreé dónde se arroja el error en google_map.js línea 83:

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

Aquí está mi componente de mapa hasta ahora. La página se carga muy bien (sin un mapa) cuando comento las líneas 58-60, las últimas tres líneas. editar: hice los cambios que @Dmitriy Nevzorov sugirió y todavía me da el mismo error.

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)

Y aquí es donde este componente del mapa se enruta en 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
Tienes dos export defaults, ¿y no sería new GoogleAPIComponent()así GoogleAPIComponent()?
gcampbell

Eliminé uno de los valores predeterminados e intenté su sugerencia. Parece que en realidad está hablando con Google Maps ahora, lo cual es bueno, pero antes de que la página se pueda cargar, arroja otro error críptico: Locations.js: 58 Tipo de error no capturado: (valor intermedio) no es una función ". ¿Alguna idea?
Mike Fleming

1
¿Qué pasa si quitas el (LocationContainer)?
gcampbell

Gracias, creo que lo entendí! Extraño, así es como lo tienen escrito en su blog. Todavía obteniendo algunos otros errores de Google Maps, los pondré aquí: 'GoogleMap: apiKey está en desuso, use bootstrapURLKeys = {{key: YOUR_API_KEY}} en su lugar. google_map.js: 689 GoogleMap: center o defaultCenterproperty debe definirse google_map.js: 699 GoogleMap: zoom o defaultZoomproperty debe definirse google_map.js: 704 '
Mike Fleming

1
No estoy seguro de los otros errores, pero podría intentar solucionar el primero:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

Respuestas:


207

Para mí sucedió cuando olvidé escribir extends React.Componental final. Sé que no es exactamente lo que USTED tenía, pero espero que otros que lean esta respuesta puedan beneficiarse de esto.


19
Hay una gran publicación en exagerada que explica por qué esto funciona exagerado.io/how-does-react-tell-a-class-from-a-function
Eric Kigathi

1
Resumen de la publicación: Distinguir entre una clase y una función en el navegador en realidad no es completamente trivial ... "La solución real es realmente simple, pero [voy en una] gran tangente para explicar por qué React terminó con esta solución. .. "bla, bla, bla, ... ->" Si no extiende React.Component, React no encontrará isReactComponent en el prototipo y no tratará el componente como una clase ".
Spinkus

Excelente. Estaba enfrentando un problema similar y su solución solucionó el problema. Pero mi sintaxis era import React, { Component } from 'react'; class extends Component. No pude entender cómo resolvió el problema reemplazando Componentcon React.Component. ¿Importa la importación?
Arun Ramachandran

70

Para mí fue porque olvidé usar la newpalabra clave al configurar el estado animado.

p.ej:

fadeAnim: Animated.Value(0),

a

fadeAnim: new Animated.Value(0),

Lo arreglaría.


1
Esto resolvió mi problema, estaba usando un caso de uso diferente, no animado, pero después de usar la nueva palabra clave lo resolvió. Gracias
Olivier JM

44
Pasé 4 horas 44 minutos y 4 segundos tratando de saber qué sucedió. Tú eres Dios.
Satheeshwaran

Sí, ese era yo también. ¡Gracias!
James Cushing, el

64

tl; dr

Si usa React Router v4, verifique su <Route/>componente si realmente usa elcomponent accesorio para pasar su componente React basado en su clase.

En términos más generales: si su clase parece estar bien, verifique si el código que la llama no intenta usarla como una función.

Explicación

Recibí este error porque estaba usando React Router v4 y accidentalmente usé el renderaccesorio en lugar del componentque estaba en el <Route/>componente para pasar mi componente que era una clase. Este fue un problema, porque renderespera (llama) una función, mientras que componentes la que funcionará en los componentes React.

Entonces en este código:

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

La línea que contiene el <Route/>componente, debería haberse escrito así:

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

Es una pena que no lo verifiquen y den un error útil para un error tan fácil de detectar.


47

Me pasó porque solía

PropTypes.arrayOf(SomeClass)

en vez de

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))


Gracias, la definición incorrecta de PropTypes fue el problema en mi caso.
Vasiliy

Esto resolvió mi problema! fue en PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,lugar de PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Doug

Gracias, realmente me preguntaba por mucho tiempo qué estaba pasando allí.
Got The Fever Media

14

Has duplicado la export defaultdeclaración. El primero se anula por el segundo, que en realidad es una función.


¡Buena atrapada! Dejé el valor predeterminado frente a GoogleApiComponent y sigo teniendo el mismo error. Alternativamente, eliminar todos los valores predeterminados me da un error de "token inesperado" en mi terminal en GoogleApiComponent.
Mike Fleming

14

Para mí, fue en ComponentName.prototypelugar de ComponentName.propTypes. auto sugerido por PhpstormIDE. Espero que ayude a alguien.


14

Experimenté el mismo problema, ocurrió porque mi ES6clase de componente no se extendía React.Component.


8

En su mayoría, estos problemas se producen cuando se omite extender Componente desde la reacción:

import React, {Component} from 'react'

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

7

Para mí fue porque usé prototipos en lugar de propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

deberia ser

MyComponent.propTypes = {

};

Exactamente el mismo caso para mí. ¡Gracias!
Tekson

6
Post.proptypes = {

}

a

Post.propTypes = {

}

alguien debería comentar cómo monitorear dicho error de una manera muy precisa.


1
Es mejor explicar su solución / respuesta con información detallada.
Dharmang

Yaah sucede, ¡bravo!
Mbanda

3

Parece que no hay un solo caso cuando aparece este error.

Me sucedió cuando no declaró el constructor en el componente statefull.

class MyComponent extends Component {

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

en vez de

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

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

3

Dos cosas que puedes verificar es,

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Asegúrate de extender React.Component
  • Use propTypes en lugar de prototipo (según IDE intellisense)

debe ser Slider.propTypes: {}
David Casanellas

2

Este es un problema general y no aparece en un solo caso. Pero, el problema común en todos los casos es que se olvida de importun componente específico (no importa si es de una biblioteca que instaló o de un componente personalizado que creó):

import {SomeClass} from 'some-library'

Cuando lo usa más tarde, sin importarlo, el compilador cree que es una función. Por lo tanto, se rompe. Este es un ejemplo común:

imports

...code...

y luego en algún lugar dentro de tu código

<Image {..some props} />

Si olvidó importar el componente <Image />, el compilador no se quejará como lo hace para otras importaciones, pero se interrumpirá cuando llegue a su código.


1

¡Para mí, fue porque accidentalmente eliminé mi rendermétodo!

Tuve una clase con un componentWillReceivePropsmétodo que ya no necesitaba, inmediatamente antes de un rendermétodo corto . En mi apuro por eliminarlo, también eliminé accidentalmente todo el rendermétodo.

Este fue un DOLOR para rastrear, ya que recibía errores de consola que apuntaban a comentarios en archivos completamente irrelevantes como la "fuente" del problema.


1

Tuve un problema similar, estaba llamando al método de renderizado incorrectamente

Dio un error:

render = () => {
    ...
}

en vez de

correcto:

render(){
    ...
}

1

Lo tuve cuando lo hice:

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

correctamente:

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

o

const foo = ...
export default foo

1

Para mí sucedió porque no envolví mi función de conexión correctamente e intenté exportar dos componentes predeterminados


1

Enfrenté este error cuando importé la clase incorrecta y me referí a la tienda incorrecta mientras usaba mobx en react-native.

Me enfrenté a un error en este fragmento:

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

@inject ("counter")
@Observer

Después de algunas correcciones como el fragmento de abajo. Resolví mi problema de esta manera.

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

@inject("counterStore")
@observer

Lo que realmente estaba mal, estaba usando la clase incorrecta en lugar de lo observerque usé Observery en lugar de lo counterStoreque usé counter. Resolví mi problema de esta manera.


1

En archivo MyComponent.js

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

Pongo alguna función relacionada con ese componente:

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

export myFunction() {
...
}

y luego en otro archivo importado esa función:

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

¿Puedes detectar el problema?

¡Olvidé las llaves, e importé MyComponentbajo nombre myFunction!

Entonces, la solución fue:

import {myFunction} from './MyComponent'

1

Experimenté esto cuando escribí una declaración de importación incorrecta al importar una función, en lugar de una clase. SiremoveMaterial es una función en otro módulo:

Correcto:

import { removeMaterial } from './ClaimForm';

Incorrecto:

import removeMaterial from './ClaimForm';

1

Recibí este error cometiendo un pequeño error. Mi error fue exportar la clase como una función en lugar de como una clase. Al final de mi archivo de clase tenía:

export default InputField();

cuando debería haber sido:

export default InputField;

0

También me he encontrado con esto, es posible que tenga un error de JavaScript dentro de su componente de reacción. Asegúrese de que si está utilizando una dependencia, está utilizando el newoperador de la clase para crear una instancia de la nueva instancia. Se lanzará un error si

this.classInstance = Class({})

en su lugar use

this.classInstance = new Class({})

verá en la cadena de error en el navegador

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

ese es el sorteo, creo.


0

Intenta detener tu HMR y presiona npm startnuevamente para reconstruir tu proyecto.
Esto, hizo que el error desapareciera, no sé por qué.


0

En mi caso escribí commenten lugar de Componentpor error

Acabo de escribir esto.

import React, { Component } from 'react';

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

En lugar de esto.

import React, { Component } from 'react';

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

no es gran cosa, pero para un principiante como yo es realmente confuso. Espero que esto sea útil.


0

En mi caso, usando JSX un componente padre estaba llamando a otros componentes sin el "<>"

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

reparar

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

0

Otro informe aquí: no funcionó como exporté:

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

en vez de

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

Tenga en cuenta la posición de los soportes. Ambos son correctos y no serán atrapados por un linter o más bonito o algo similar. Me llevó un tiempo localizarlo.


0

En mi caso, accidentalmente puse el nombre del componente ( Home) como primer argumento paraconnect funcionar mientras se suponía que debía estar al final. duh

Este, seguramente, me dio el error:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Pero este funcionó, seguramente, bien:

export default connect(mapStateToProps, mapDispatchToProps)(Home)

0

Esto ocurrió cuando accidentalmente puse un nombre renderincorrecto a mi función:

import React from 'react';

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

Mi instancia de este error simplemente fue causada porque mi clase no tenía un rendermétodo adecuado .


0

En realidad todo el problema redux connect. soluciones:

Correcto :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Mal y error :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)

-1

Para mí fue una importación incorrecta de un reductor en rootReducer.js. Importé el contenedor en lugar del archivo reductor.

Ejemplo

import settings from './pages/Settings';

Pero seguro que debería ser

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

Donde el directorio de configuración contiene los siguientes archivos actions.js, index.js, reducer.js.

Para verificarlo, puede registrar los reductores arg de la función afirmarReducerShape () desde redux / es / redux.js.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.