React this.setState कोई फ़ंक्शन नहीं है


288

मैं रिएक्ट में नया हूँ और एक एपीआई के साथ काम करने वाला ऐप लिखने की कोशिश कर रहा हूँ। मुझे यह त्रुटि मिलती रहती है:

TypeError: this.setState एक फ़ंक्शन नहीं है

जब मैं एपीआई प्रतिक्रिया को संभालने की कोशिश करता हूं। मुझे संदेह है कि यह इस बाध्यकारी के साथ कुछ गलत है लेकिन मैं यह पता नहीं लगा सकता कि इसे कैसे ठीक किया जाए। यहाँ मेरे घटक का कोड है:

var AppMain = React.createClass({
    getInitialState: function() {
        return{
            FirstName: " "
        };
    },
    componentDidMount:function(){
        VK.init(function(){
            console.info("API initialisation successful");
            VK.api('users.get',{fields: 'photo_50'},function(data){
                if(data.response){
                    this.setState({ //the error happens here
                        FirstName: data.response[0].first_name
                    });
                    console.info(this.state.FirstName);
                }

            });
        }, function(){
        console.info("API initialisation failed");

        }, '5.34');
    },
    render:function(){
        return (
            <div className="appMain">
            <Header  />
            </div>
        );
    }
});

जवाबों:


348

कॉलबैक एक अलग संदर्भ में किया जाता है। आप की जरूरत bindकरने के लिए thisआदेश कॉलबैक अंदर उपयोग किया है में:

VK.api('users.get',{fields: 'photo_50'},function(data){
    if(data.response){
        this.setState({ //the error happens here
            FirstName: data.response[0].first_name
        });
        console.info(this.state.FirstName);
    }

}.bind(this));

संपादित करें: ऐसा लगता है कि आपको कॉल initऔर apiकॉल दोनों को बाँधना है :

VK.init(function(){
        console.info("API initialisation successful");
        VK.api('users.get',{fields: 'photo_50'},function(data){
            if(data.response){
                this.setState({ //the error happens here
                    FirstName: data.response[0].first_name
                });
                console.info(this.state.FirstName);
            }

        }.bind(this));
    }.bind(this), function(){
    console.info("API initialisation failed");

    }, '5.34');

@TravisReeder, नहीं। ट्यूटोरियल में बाँध का कोई उल्लेख नहीं है।
Tor Haugen

8
शायद 2.5 साल पहले था। 😁
ट्रैविस रीडर

1
मैंने समस्या को हल करने के लिए तीर फ़ंक्शन का उपयोग किया। मदद के लिए धन्यवाद
तरुण नागपाल

क्या "कॉलबैक एक अलग संदर्भ में किया जाता है" से किसी का क्या मतलब है, इसके बारे में विस्तार से बता सकते हैं?
एसबी

135

आप ES6 तीर फ़ंक्शन के साथ .bind (यह) की आवश्यकता से बच सकते हैं।

VK.api('users.get',{fields: 'photo_50'},(data) => {
        if(data.response){
            this.setState({ //the error happens here
                FirstName: data.response[0].first_name
            });
            console.info(this.state.FirstName);
        }

    });

1
यह अच्छा काम करता है। वास्तव में, es6 की फ़ाइल में फ़ंक्शन के कीवर्ड को नहीं दिखाया जाना चाहिए।
JChen___

6
आपके उत्तर से मुझे मदद मिली :-) एक ES6 वर्ग और RN 0.34 का उपयोग करते हुए, मैंने कॉलबैक फ़ंक्शन के लिए "यह" बांधने के दो तरीके पाए। 1) onChange={(checked) => this.toggleCheckbox()}, 2) onChange={this.toggleCheckbox.bind(this)}
देवदंक १६'१६

यह तब तक अच्छा है जब तक आपको पुराने ब्राउज़रों का समर्थन करने की आवश्यकता नहीं है।
उपयोगकर्ता

सही समाधान
हितेश साहू

2
GMsoF, वे दो समाधान काम करते हैं क्योंकि a) जब आप करते हैं .bind(this), तो यह thisमूल संदर्भ का मान सेट करता है, जहां this.toggleCheckbox()से कॉल किया जाता है, अन्यथा thisयह वास्तव में निष्पादित होने पर संदर्भित होता है। बी) वसा तीर समाधान काम करता है क्योंकि यह के मूल्य को बरकरार रखता है this, इसलिए यह आपको हिंसक रूप से मूल्य में परिवर्तन नहीं करके मदद कर रहा है this। जावास्क्रिप्ट में, thisबस वर्तमान क्षेत्र को संदर्भित करता है, इसलिए यदि आप एक फ़ंक्शन लिखते हैं, तो thisवह फ़ंक्शन है। यदि आप इसके अंदर एक फंक्शन डालते हैं, तो यह thisउस चाइल्ड फंक्शन के अंदर है। फैट तीर संदर्भ रखते हैं कि कहाँ से कहा जाता है
agm1984

37

विधि thisलागू करने से पहले आप एक संदर्भ भी सहेज सकते हैं api:

componentDidMount:function(){

    var that = this;

    VK.init(function(){
        console.info("API initialisation successful");
        VK.api('users.get',{fields: 'photo_50'},function(data){
            if(data.response){
                that.setState({ //the error happens here
                    FirstName: data.response[0].first_name
                });
                console.info(that.state.FirstName);
            }
        });
    }, function(){
        console.info("API initialisation failed");

    }, '5.34');
},

32

रिएक्ट सभी तरीकों से इसे बांधने की सलाह देता है जो इसे classस्वयं के बजाय इसका उपयोग करने की आवश्यकता है function

constructor(props) {
    super(props)
    this.onClick = this.onClick.bind(this)
}

 onClick () {
     this.setState({...})
 }

या आप arrow functionइसके बजाय उपयोग कर सकते हैं ।


14

आपको केवल अपने ईवेंट को बांधने की आवश्यकता है

पूर्व के लिए-

// place this code to your constructor

this._handleDelete = this._handleDelete.bind(this);

// and your setState function will work perfectly

_handleDelete(id){

    this.state.list.splice(id, 1);

    this.setState({ list: this.state.list });

    // this.setState({list: list});

}

10

अब ES6 में एरो फंक्शन है जो वास्तव में मददगार है यदि आप वास्तव में बाइंड (इस) एक्सप्रेशन के साथ कन्फ्यूज हैं तो आप एरो फंक्शन ट्राई कर सकते हैं

ऐसा ही मैं करता हूँ।

componentWillMount() {
        ListApi.getList()
            .then(JsonList => this.setState({ List: JsonList }));
    }

 //Above method equalent to this...
     componentWillMount() {
         ListApi.getList()
             .then(function (JsonList) {
                 this.setState({ List: JsonList });
             }.bind(this));
 }

8

यदि आप तीर फ़ंक्शन का उपयोग करते हैं, तो आपको इसे किसी स्थानीय चर पर असाइन करने की आवश्यकता नहीं है। एरो फ़ंक्शंस स्वचालित रूप से बाध्यकारी हो जाते हैं और आप गुंजाइश से संबंधित मुद्दों से दूर रह सकते हैं।

नीचे दिए गए कोड बताते हैं कि विभिन्न परिदृश्यों में तीर फ़ंक्शन का उपयोग कैसे करें

componentDidMount = () => {

    VK.init(() => {
        console.info("API initialisation successful");
        VK.api('users.get',{fields: 'photo_50'},(data) => {
            if(data.response){
                that.setState({ //this available here and you can do setState
                    FirstName: data.response[0].first_name
                });
                console.info(that.state.FirstName);
            }
        });
    }, () => {
        console.info("API initialisation failed");

    }, '5.34');
 },

5

अब es6 / 7 के साथ प्रतिक्रिया करें आप फ़ंक्शन को इस तरह से तीर फ़ंक्शन के साथ वर्तमान संदर्भ में बाँध सकते हैं, अनुरोध कर सकते हैं और इस तरह वादे हल कर सकते हैं:

listMovies = async () => {
 const request = await VK.api('users.get',{fields: 'photo_50'});
 const data = await request.json()
 if (data) {
  this.setState({movies: data})
 }
}

इस विधि के साथ आप आसानी से इस फ़ंक्शन को कंपोनेंटडिमाउंट में कॉल कर सकते हैं और अपने HTML को अपने रेंडर फ़ंक्शन में रेंडर करने से पहले डेटा की प्रतीक्षा कर सकते हैं।

मुझे आपकी परियोजना का आकार नहीं पता है, लेकिन मैं व्यक्तिगत रूप से डेटा में हेरफेर करने के लिए घटक की वर्तमान स्थिति का उपयोग करने के खिलाफ सलाह देता हूं। आपको Redux या Flux जैसे बाहरी राज्य का उपयोग करना चाहिए या उसके लिए कुछ और करना चाहिए।


5

तीर फ़ंक्शन का उपयोग करें, क्योंकि तीर फ़ंक्शन पैरेंट स्कोप को इंगित करते हैं और यह उपलब्ध होगा। (बाइंड तकनीक का विकल्प)


1
एक शानदार रसीला समाधान
चुन

एक ही मुद्दा होने के बावजूद कॉल में एरो फंक्शन के रूप में विधि का उपयोग किया जाता है, लेकिन मुझे लगता है कि मुझे राज्य फ़ंक्शन को इस तरह लागू करना होगा, और वास्तव में मैंने क्या किया है
कार्माइन टैम्बस्किया

3

यहाँ इस संदर्भ को बदला जा रहा है। प्रतिक्रिया वर्ग का संदर्भ रखने के लिए तीर फ़ंक्शन का उपयोग करें।

        VK.init(() => {
            console.info("API initialisation successful");
            VK.api('users.get',{fields: 'photo_50'},(data) => {
                if(data.response){
                    this.setState({ //the error happens here
                        FirstName: data.response[0].first_name
                    });
                    console.info(this.state.FirstName);
                }

            });
        }, function(){
        console.info("API initialisation failed");

        }, '5.34');

1

यदि आप ऐसा कर रहे हैं और अभी भी कोई समस्या है, तो मेरी समस्या यह है कि मैं दो चर को एक ही नाम कह रहा था।

मेरे पास companiesफायरबेस से लाई गई एक वस्तु के रूप में था , और फिर कॉल करने की कोशिश कर रहा था this.setState({companies: companies})- यह स्पष्ट कारणों से काम नहीं कर रहा था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.