Получение «Невозможно вызвать класс как функцию» в моем проекте React


130

Я пытаюсь добавить в свой проект компонент карты React, но получаю ошибку. Я использую сообщение в блоге Fullstack React как ссылку. Я отследил, где возникает ошибка в строке 83 google_map.js:

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

Вот мой компонент карты. Страница загружается нормально (без карты), когда я закомментировал строки 58-60, последние три строки. edit: я внес изменения, которые предложил @Dmitriy Nevzorov, и он по-прежнему дает мне ту же ошибку.

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)

И вот где этот компонент карты маршрутизируется в 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
У вас есть два export default, а не будет new GoogleAPIComponent()ли GoogleAPIComponent()?
gcampbell

Я удалил одно из значений по умолчанию и попробовал ваше предложение. Похоже, сейчас он действительно разговаривает с Google Maps, и это хорошо, но прежде чем страница сможет загрузиться, она выдает еще одну загадочную ошибку: Locations.js: 58 Uncaught TypeError: (промежуточное значение) не является функцией ". Есть идеи?
Майк Флеминг

1
Что, если вы удалите (LocationContainer)?
gcampbell

Спасибо, я думаю, что понял! Странно, вот как они написали в своем блоге. По-прежнему получаю несколько других ошибок из Google Maps, я помещаю их здесь: 'GoogleMap: apiKey устарел, используйте вместо этого bootstrapURLKeys = {{key: YOUR_API_KEY}}. google_map.js: 689 GoogleMap: center или defaultCenterproperty должен быть определен google_map.js: 699 GoogleMap: zoom или defaultZoomproperty должен быть определен google_map.js: 704 '
Майк Флеминг

1
Я не уверен насчет других ошибок, но вы можете попробовать это исправить первую:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

Ответы:


207

Для меня это случилось, когда я забыл написать extends React.Componentв конце. Я знаю, что это не совсем то, что у ВАС было, но, надеюсь, другие, читающие этот ответ, могут извлечь из этого пользу.


19
Там здорово пост в переусердствовал , что объясняет , почему это работает overreacted.io/how-does-react-tell-a-class-from-a-function
Эрик Kigathi

1
Краткое содержание сообщения: Различение между классом и функцией в браузере на самом деле не совсем тривиально ... «Фактическое решение действительно простое, но [я собираюсь] сделать важный шаг, чтобы объяснить, почему React остановился на этом решении. .. "бла, бла, бла, ... ->" Если вы не расширите React.Component, React не найдет isReactComponent в прототипе и не будет рассматривать компонент как класс. "
spinkus

Отлично. Я столкнулся с аналогичной проблемой, и ваше решение устранило проблему. Но мой синтаксис был import React, { Component } from 'react'; class extends Component. Я не мог понять, как это решило проблему, заменив Componentна React.Component. Имеет ли значение импорт?
Арун Рамачандран,

70

Для меня это было потому, что я забыл использовать newключевое слово при настройке состояния Animated.

например:

fadeAnim: Animated.Value(0),

в

fadeAnim: new Animated.Value(0),

исправлю это.


1
Это решило мою проблему, я использовал другой вариант использования, а не анимацию, но после использования ключевого слова new решил его. Спасибо
Olivier JM

4
Потратил 4 часа 44 минуты и 4 секунды, пытаясь узнать, что произошло. Ты Бог.
Satheeshwaran 04

Ага, это тоже был я. Спасибо!
Джеймс Кушинг

64

ТЛ; др

Если вы используете React Router v4, проверьте свой <Route/>компонент, действительно ли вы используете componentопору для передачи компонента React на основе вашего класса!

В более общем плане: если ваш класс выглядит нормально, проверьте, не пытается ли вызывающий его код использовать его как функцию.

объяснение

Я получил эту ошибку, потому что я использовал React Router v4, и я случайно использовал renderопору вместо той, что componentв <Route/>компоненте, чтобы передать свой компонент, который был классом. Это было проблемой, потому что renderожидает (вызывает) функцию, componentкоторая будет работать с компонентами React.

Итак, в этом коде:

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

Строка, содержащая <Route/>компонент, должна была быть написана так:

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

Обидно, что они не проверяют это и выдают полезную ошибку за такую ​​легко обнаруживаемую ошибку.


47

Со мной случилось, потому что я использовал

PropTypes.arrayOf(SomeClass)

вместо того

PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))


Спасибо, неправильное определение PropTypes было проблемой в моем случае.
Василий

это решило мою проблему! был PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,вместо PropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Дуг

Спасибо, очень долго думал, что там не так!
Получил The Fever Media

14

Вы продублировали export defaultдекларацию. Первый заменяется вторым, который на самом деле является функцией.


Хороший улов! Я оставил значение по умолчанию перед GoogleApiComponent, но все равно получаю ту же ошибку. Кроме того, удаление всех значений по умолчанию дает мне "неожиданную ошибку токена" в моем терминале в GoogleApiComponent.
Mike Fleming

14

Для меня это было ComponentName.prototypeвместо ComponentName.propTypes. авто предложено PhpstormIDE. Надеюсь, это кому-то поможет.


14

У меня возникла та же проблема, потому что мой ES6класс компонента не расширялся React.Component.


8

В основном эти проблемы возникают, когда вы пропускаете расширение Component из response:

import React, {Component} from 'react'

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

7

Для меня это было потому, что я использовал прототип вместо propTypes

class MyComponent extends Component {

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

MyComponent.prototype = {

};

это должно быть

MyComponent.propTypes = {

};

Точно такой же случай для меня. Спасибо!
Tekson

6
Post.proptypes = {

}

в

Post.propTypes = {

}

кто-то должен прокомментировать, как очень точно отслеживать такую ​​ошибку.


1
Лучше пояснить свое решение / ответ более подробной информацией.
Дхарманг

Да, такое бывает, Браво!
Mbanda

3

Похоже, что нет ни одного случая появления этой ошибки.

Со мной случилось, когда я не объявлял конструктор в компоненте с полным состоянием.

class MyComponent extends Component {

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

вместо того

class MyComponent extends Component {

    constructor(props) {
        super(props);
    }

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

3

Вы можете проверить две вещи:

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

Slider.propTypes = {
    // accessibility: PropTypes.bool,
}
  • Убедитесь, что вы расширяете React.Component
  • Используйте propTypes вместо прототипа (согласно IDE intellisense)

должно быть Slider.propTypes: {}
Дэвид Касанеллас,

2

Это общая проблема, не возникающая ни в одном случае. Но общая проблема во всех случаях заключается в том, что вы забываете importо конкретном компоненте (не имеет значения, из установленной вами библиотеки или из созданного вами компонента):

import {SomeClass} from 'some-library'

Когда вы используете его позже, не импортируя, компилятор думает, что это функция. Поэтому ломается. Это типичный пример:

imports

...code...

а затем где-то внутри вашего кода

<Image {..some props} />

Если вы забыли импортировать компонент, <Image />компилятор не будет жаловаться, как при импорте других компонентов , но сломается, когда достигнет вашего кода.


1

Для меня это произошло потому, что я случайно удалил свой renderметод!

У меня был класс с componentWillReceivePropsметодом, который мне больше не нужен, непосредственно перед коротким renderметодом. В спешке удаляя его, я случайно удалил и весь renderметод.

Это была БОЛЬ, которую нужно было выследить, так как я получал консольные ошибки, указывающие на комментарии в совершенно нерелевантных файлах как на «источник» проблемы.


1

У меня была аналогичная проблема, я неправильно вызывал метод рендеринга

Выдал ошибку:

render = () => {
    ...
}

вместо того

верный:

render(){
    ...
}

1

У меня было такое, когда я так делал:

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

правильно:

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

или

const foo = ...
export default foo

1

Для меня это произошло потому, что я не обернул свою функцию подключения должным образом и попытался экспортировать два компонента по умолчанию


1

Я столкнулся с этой ошибкой, когда импортировал неправильный класс и ссылался на неправильный магазин при использовании mobx в react-native.

Я столкнулся с ошибкой в ​​этом фрагменте:

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

@inject ("counter")
@Observer

После нескольких исправлений, как показано ниже. Так я решил свою проблему.

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

@inject("counterStore")
@observer

Что на самом деле было не так, я использовал неправильный класс вместо того, observerчто использовал, Observerи вместо того, чтобы counterStoreиспользовать counter. Так я решил свою проблему.


1

В файле MyComponent.js

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

Я добавляю некоторую функцию, связанную с этим компонентом:

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

export myFunction() {
...
}

а затем в другом файле импортировали эту функцию:

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

Вы можете определить проблему?

Я забыл фигурные скобки и импортировал MyComponentпод именемmyFunction !

Итак, исправление было:

import {myFunction} from './MyComponent'

1

Я испытал это, когда неправильно написал оператор импорта при импорте функции, а не класса. ЕслиremoveMaterial это функция в другом модуле:

Правильно:

import { removeMaterial } from './ClaimForm';

Неправильно:

import removeMaterial from './ClaimForm';

1

Я получил эту ошибку, сделав небольшую ошибку. Моя ошибка заключалась в экспорте класса как функции, а не как класса. Внизу моего файла класса у меня было:

export default InputField();

когда это должно было быть:

export default InputField;

0

Я также столкнулся с этим, возможно, у вас есть ошибка javascript внутри вашего компонента реакции. Убедитесь, что при использовании зависимости вы используете newоператор класса для создания нового экземпляра. Ошибка выдает, если

this.classInstance = Class({})

вместо этого используйте

this.classInstance = new Class({})

вы увидите в цепочке ошибок в браузере

at ReactCompositeComponentWrapper._constructComponentWithoutOwner

я считаю, что это раздача.


0

Попробуйте остановить HMR и нажмите еще npm startраз, чтобы восстановить проект.
Это заставило ошибку исчезнуть, не знаю почему.


0

В моем случае я написал comment вместо Componentошибочно

Я только что это написал.

import React, { Component } from 'react';

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

Вместо этого.

import React, { Component } from 'react';

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

это не имеет большого значения, но для новичка вроде меня это действительно сбивает с толку. Надеюсь, это будет полезно.


0

В моем случае, используя JSX, родительский компонент вызывал другие компоненты без "<>"

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

исправление

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

0

Другой отчет здесь: Не сработало, когда я экспортировал:

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

вместо того

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

Обратите внимание на положение скобок. Оба правильные и не попадутся ни линтеру, ни красивее, ни чему-то подобному. Мне потребовалось время, чтобы разыскать его.


0

В моем случае я случайно поставил имя компонента ( Home) в качестве первого аргумента функцииconnect функции, хотя он должен был быть в конце. Дух.

Этот, конечно же, дал мне ошибку:

export default connect(Home)(mapStateToProps, mapDispatchToProps)

Но этот сработал, конечно, нормально:

export default connect(mapStateToProps, mapDispatchToProps)(Home)

0

Это произошло, когда я случайно renderнеправильно назвал свою функцию:

import React from 'react';

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

Мой экземпляр этой ошибки был вызван просто тем, что у моего класса не было подходящего renderметода.


0

Собственно все проблемы redux подключаются. решения:

Правильно :

export default connect(mapStateToProps, mapDispatchToProps)(PageName)

Неправильно и ошибка :

export default connect(PageName)(mapStateToProps, mapDispatchToProps)

-1

Для меня это был неправильный импорт редуктора в rootReducer.js. Я импортировал контейнер вместо файла-редуктора.

пример

import settings from './pages/Settings';

Но конечно должно быть

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

Где каталог настроек содержит следующие файлы actions.js, index.js, reducer.js.

Чтобы проверить это, вы можете зарегистрировать аргументы redux для функции assertReducerShape () из файла redux / es / redux.js.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.