รับ "ไม่สามารถเรียกคลาสเป็นฟังก์ชัน" ในโครงการ React ของฉัน


132

ฉันกำลังพยายามเพิ่มองค์ประกอบ React map ในโปรเจ็กต์ของฉัน แต่พบข้อผิดพลาด ฉันใช้บล็อกโพสต์ของ Fullstack React เป็นข้อมูลอ้างอิง ฉันติดตามว่าข้อผิดพลาดเกิดขึ้นที่ไหนใน google_map.js บรรทัด 83:

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

นี่คือส่วนประกอบแผนที่ของฉันจนถึงตอนนี้ หน้าเว็บโหลดได้ดี (ไม่มีแผนที่) เมื่อฉันแสดงความคิดเห็นบรรทัดที่ 58-60 สามบรรทัดสุดท้าย แก้ไข: ฉันได้ทำการเปลี่ยนแปลงที่ @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: (ค่ากลาง) ไม่ใช่ฟังก์ชัน "มีความคิดอย่างไร
Mike Fleming

1
จะเกิดอะไรขึ้นถ้าคุณลบ(LocationContainer)?
gcampbell

ขอบคุณฉันคิดว่าเข้าใจแล้ว! แปลกนั่นคือสิ่งที่พวกเขาเขียนไว้ในบล็อกโพสต์ ยังคงได้รับข้อผิดพลาดอื่น ๆ จาก Google แผนที่ฉันจะใส่ไว้ที่นี่: '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 '
Mike Fleming

1
ฉันไม่แน่ใจเกี่ยวกับข้อผิดพลาดอื่น ๆ แต่คุณสามารถลองสิ่งนี้เพื่อแก้ไขข้อผิดพลาดแรก:export default new GoogleApiComponent({ bootstrapURLKeys: MY_API_KEY })
gcampbell

คำตอบ:


207

สำหรับฉันมันเกิดขึ้นเมื่อฉันลืมเขียนextends React.Componentตอนท้าย ฉันรู้ว่ามันไม่ใช่สิ่งที่คุณมี แต่คนอื่น ๆ ที่อ่านคำตอบนี้จะได้รับประโยชน์จากสิ่งนี้หวังว่า


19
มีโพสต์ที่ยอดเยี่ยมในการตอบสนองมากเกินไปซึ่งอธิบายว่าเหตุใดสิ่งนี้จึงทำงานเกิน
จริง io/how-does-react-tell-a-class-from-a-function

1
บทสรุปของโพสต์: การแยกแยะระหว่างคลาสและฟังก์ชันในเบราว์เซอร์นั้นไม่ได้เป็นเรื่องเล็กน้อยอย่างสิ้นเชิง ... "วิธีแก้ปัญหาที่แท้จริงนั้นง่ายมาก แต่ [ฉันกำลังใช้แทนเจนต์] ขนาดใหญ่เพื่ออธิบายว่าเหตุใด React จึงลงเอยด้วยโซลูชันนี้ .. "blah, blah, blah, ... ->" หากคุณไม่ขยาย React.Component React จะไม่พบ isReactComponent บนต้นแบบและจะไม่ถือว่าองค์ประกอบเป็นคลาส "
spinkus

ยิ่งใหญ่ ฉันประสบปัญหาที่คล้ายกันและวิธีการแก้ปัญหาของคุณได้รับการแก้ไขแล้ว แต่ไวยากรณ์ของฉันคือimport React, { Component } from 'react'; class extends Component. ฉันไม่สามารถเข้าใจวิธีการทำแก้ไขปัญหานี้โดยการแทนที่ด้วยComponent React.Componentการนำเข้ามีความสำคัญหรือไม่?
อรุณรามจันทร์

72

สำหรับฉันมันเป็นเพราะฉันลืมใช้ไฟล์ newคีย์เวิร์ดเมื่อตั้งค่าสถานะเคลื่อนไหว

เช่น:

fadeAnim: Animated.Value(0),

ถึง

fadeAnim: new Animated.Value(0),

จะแก้ไขได้


1
สิ่งนี้ช่วยแก้ปัญหาของฉันได้ฉันใช้กรณีการใช้งานอื่นไม่ใช่ภาพเคลื่อนไหว แต่หลังจากใช้คำหลักใหม่แก้ไขได้ ขอบคุณ
Olivier JM

5
ใช้เวลา 4 ชั่วโมง 44 นาที 4 วินาทีเพื่อพยายามรู้ว่าเกิดอะไรขึ้น คุณเป็นพระเจ้า
Satheeshwaran

ใช่นั่นคือฉันด้วย ขอบคุณ!
James Cushing

64

TL; DR

หากคุณใช้ React Router v4 ให้ตรวจสอบ<Route/>ส่วนประกอบของคุณว่าคุณใช้ไฟล์component prop เพื่อส่งผ่านองค์ประกอบ React ตามคลาสของคุณหรือไม่!

โดยทั่วไป: ถ้าชั้นเรียนของคุณดูโอเคให้ตรวจสอบว่ารหัสที่เรียกว่าไม่พยายามใช้เป็นฟังก์ชันหรือไม่

คำอธิบาย

ฉันได้รับข้อผิดพลาดนี้เนื่องจากฉันใช้ React Router v4 และฉันบังเอิญใช้renderprop แทน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 ที่ไม่ถูกต้องเป็นปัญหาในกรณีของฉัน
Vasiliy

สิ่งนี้ช่วยแก้ปัญหาของฉันได้! PropTypes.oneOfType([SomeClass, SomeOtherClass]).isRequired,แทนที่จะ เป็นPropTypes.oneOfType([PropTypes.instanceOf(SomeClass), PropTypes.instanceOf(SomeOtherClass)]).isRequired,
Doug

ขอบคุณจริงๆสงสัยมานานแล้วว่าเกิดอะไรขึ้น!
Got The Fever Media

14

คุณมีexport defaultการประกาศซ้ำ อันแรกถูกแทนที่ด้วยอันที่สองซึ่งเป็นฟังก์ชัน


จับดี! ฉันทิ้งค่าเริ่มต้นไว้หน้า GoogleApiComponent และฉันก็ยังคงได้รับข้อผิดพลาดเดียวกัน อีกวิธีหนึ่งการลบค่าเริ่มต้นทั้งหมดทำให้ฉันมีข้อผิดพลาด "โทเค็นที่ไม่คาดคิด" ในเทอร์มินัลของฉันบน GoogleApiComponent
Mike Fleming

14

สำหรับผมมันเป็นแทนComponentName.prototype ComponentName.propTypesแนะนำอัตโนมัติโดยPhpstormIDE หวังว่ามันจะช่วยใครสักคน


14

ฉันประสบปัญหาเดียวกันนี้เกิดขึ้นเนื่องจากES6คลาสส่วนประกอบของฉันไม่ได้ขยายออกReact.Componentไป


8

ส่วนใหญ่ปัญหาเหล่านี้เกิดขึ้นเมื่อคุณพลาดการขยายComponentจากการตอบสนอง:

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
เป็นการดีกว่าที่จะอธิบายวิธีแก้ปัญหา / คำตอบของคุณพร้อมข้อมูลโดยละเอียด
ธรรมมัง

มันเกิดขึ้น Bravo!
Mbanda

3

ดูเหมือนว่าจะไม่มีกรณีเดียวเมื่อข้อผิดพลาดนี้ปรากฏขึ้น

เกิดขึ้นกับฉันเมื่อฉันไม่ได้ประกาศตัวสร้างในองค์ประกอบ statefull

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: {}
David Casanellas

2

นี่เป็นปัญหาทั่วไปและไม่ปรากฏในกรณีเดียว แต่ปัญหาที่พบบ่อยในทุกกรณีคือคุณลืมimportส่วนประกอบเฉพาะ (ไม่สำคัญว่าจะมาจากไลบรารีที่คุณติดตั้งหรือส่วนประกอบที่สร้างขึ้นเองที่คุณสร้างขึ้น):

import {SomeClass} from 'some-library'

เมื่อคุณใช้ในภายหลังโดยไม่นำเข้าคอมไพเลอร์จะคิดว่ามันเป็นฟังก์ชัน ดังนั้นมันจึงแตก นี่เป็นตัวอย่างทั่วไป:

imports

...code...

แล้วก็อยู่ในโค้ดของคุณ

<Image {..some props} />

หากคุณลืมนำเข้าส่วนประกอบ<Image />คอมไพเลอร์จะไม่บ่นเหมือนกับที่ทำกับการนำเข้าอื่น ๆ แต่จะหยุดทำงานเมื่อถึงรหัสของคุณ


1

สำหรับฉันมันเป็นเพราะฉันเผลอลบrenderวิธีการของฉัน!

ฉันมีคลาสที่มีcomponentWillReceivePropsวิธีการที่ฉันไม่ต้องการอีกต่อไปโดยนำหน้าrenderวิธีการสั้น ๆทันที ด้วยความเร่งรีบของฉันที่จะลบมันออกไปฉันก็ลบทั้งหมดโดยบังเอิญrenderวิธีการ

นี่เป็นความเจ็บปวดในการติดตามเนื่องจากฉันได้รับข้อผิดพลาดของคอนโซลที่ชี้ไปที่ความคิดเห็นในไฟล์ที่ไม่เกี่ยวข้องโดยสิ้นเชิงว่าเป็น "แหล่งที่มา" ของปัญหา


1

ฉันมีปัญหาที่คล้ายกันฉันเรียกวิธีการแสดงผลไม่ถูกต้อง

ให้ข้อผิดพลาด:

render = () => {
    ...
}

แทน

แก้ไข:

render(){
    ...
}


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

ฉันพบปัญหานี้เช่นกันอาจเป็นไปได้ว่าคุณมีข้อผิดพลาดของจาวาสคริปต์ภายในองค์ประกอบการตอบสนองของคุณ ตรวจสอบให้แน่ใจว่าคุณใช้การอ้างอิงหรือไม่คุณกำลังใช้ตัว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ทำงานในขณะที่มันควรจะอยู่ในตอนท้าย duh

สิ่งนี้ทำให้ฉันเกิดข้อผิดพลาดอย่างแน่นอน:

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

ในการตรวจสอบคุณสามารถบันทึก reducers arg ของฟังก์ชัน assertReducerShape () จาก redux / es / redux.js

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.