क्यों कॉलिंग प्रतिक्रिया सेटस्टेट विधि राज्य को तुरंत म्यूट नहीं करती है?


326

मैं प्रपत्र अनुभाग पढ़ रहा हूँप्रलेखन और onChangeउपयोग को प्रदर्शित करने के लिए इस कोड को आज़माया ( JSBIN )।

var React= require('react');

var ControlledForm= React.createClass({
    getInitialState: function() {
        return {
            value: "initial value"
        };
    },

    handleChange: function(event) {
        console.log(this.state.value);
        this.setState({value: event.target.value});
        console.log(this.state.value);

    },

    render: function() {
        return (
            <input type="text" value={this.state.value} onChange={this.handleChange}/>
        );
    }
});

React.render(
    <ControlledForm/>,
  document.getElementById('mount')
);

जब मैं <input/>ब्राउज़र में मूल्य को अपडेट करता हूं , तो कॉलबैक के console.logअंदर दूसरा पहले handleChangeके समान प्रिंट करता है , मैं कॉलबैक के दायरे में परिणाम क्यों नहीं देख सकता हूं ?valueconsole.logthis.setState({value: event.target.value})handleChange


यदि आप हुक का उपयोग कर रहे हैं, तो तुरंत उपयोग परिवर्तन को प्रतिबिंबित नहीं करते हुए उपयोग की विधि पर एक नज़र डालें ।
एमिल बर्जरोन

जवाबों:


615

रिएक्ट के दस्तावेज से :

setState()तुरंत उत्परिवर्तन नहीं करता है, this.stateलेकिन एक लंबित राज्य संक्रमण बनाता है। this.stateइस पद्धति को कॉल करने के बाद एक्सेस करना मौजूदा मूल्य को संभावित रूप से वापस कर सकता है। कॉल के समकालिक संचालन की कोई गारंटी नहीं है setStateऔर प्रदर्शन लाभ के लिए कॉलों को बैच दिया जा सकता है।

यदि आप चाहते हैं कि राज्य परिवर्तन होने के बाद कोई कार्य निष्पादित किया जाए, तो इसे कॉलबैक के रूप में पास करें।

this.setState({value: event.target.value}, function () {
    console.log(this.state.value);
});

अच्छा उत्तर। मुझे जो अवलोकन करने की आवश्यकता है, वह वैल्यूलिंक का उपयोग करने के लिए सावधान रहना चाहिए। यह अच्छा काम करता है अगर आपको इनपुट को फॉर्मेट / मास्क नहीं करना है।
ढेरिक

42
तुम भी बाहर की जाँच करना चाहते हो सकता है componentDidUpdate। राज्य बदलने के बाद इसे बुलाया जाएगा।
कीसोक्स

1
त्वरित प्रश्न अगर मैं कर सकता हूं, तो एक बार हम देखें कि हम फ़ंक्शन को सेट करें जिसे हमें सेटबैक करने के लिए कॉलबैक के रूप में आवश्यक है, मैं उम्मीद कर रहा था कि रेंडर करने से पहले पहले फंक को निष्पादित किया जाएगा () कहा जाता है। लेकिन मैं देख रहा हूं कि ऑर्डर सेटलेट () -> रेंडर () -> सेटस्टेट्स कॉलबैक () है। क्या यह सामान्य है? क्या होगा यदि हम कॉलबैक में हमारे द्वारा किए गए सामान के आधार पर हमारे रेंडर को नियंत्रित करना चाहते हैं? shouldComponentUpdate ?
सेमीज़ाबोई

2
किसी घटक की बदलती स्थिति हमेशा एक पुन: रेंडर को ट्रिगर करेगी जब तक shouldComponentUpdateकि उसमें निर्दिष्ट व्यवहार न हो। वास्तव में आप उस कॉलबैक में क्या करने की कोशिश कर रहे हैं जो आप उस तक पहुंचा रहे हैं setStateजिसे आप फिर से प्रस्तुत करना चाहते हैं?
माइकल पार्कर

4
...क्यों? क्या कोई इसे सही ठहरा सकता है?
जैकहैसकेबोर्ड

49

जैसा कि रिएक्ट डॉक्यूमेंटेशन में बताया गया है, setStateसिंक्रोनाइज्ड तरीके से निकाल दिए जाने की कोई गारंटी नहीं है , इसलिए आपका console.logअपडेट होने से पहले की स्थिति वापस आ सकती है।

माइकल पार्कर में कॉलबैक पास करने का उल्लेख है setState। राज्य परिवर्तन के बाद तर्क को संभालने का एक और तरीका componentDidUpdateजीवनचक्र विधि के माध्यम से है , जो कि रिएक्ट डॉक्स में अनुशंसित विधि है।

आमतौर पर हम इसके बजाय ऐसे लॉजिक के लिए कंपोनेंटड्यूडेट () का उपयोग करने की सलाह देते हैं।

यह विशेष रूप से उपयोगी है जब क्रमिक रूप से setStateनिकाल दिया जा सकता है , और आप प्रत्येक राज्य परिवर्तन के बाद उसी फ़ंक्शन को आग लगाना चाहेंगे। प्रत्येक में एक कॉलबैक जोड़ने के बजाय , यदि आवश्यक हो, तो अंदर विशिष्ट तर्क के साथ setState, आप फ़ंक्शन को अंदर रख सकते हैं componentDidUpdate

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}

16

आप ES7 async / प्रतीक्षा का उपयोग करके देख सकते हैं। उदाहरण के लिए अपने उदाहरण का उपयोग कर:

handleChange: async function(event) {
    console.log(this.state.value);
    await this.setState({value: event.target.value});
    console.log(this.state.value);
}

आपका उत्तर अन्य उच्च गुणवत्ता वाले उत्तर से कैसे भिन्न है?
टॉड

9
अन्य उत्तर सेटस्टेट () में कॉलबैक का उपयोग करने के संबंध में है। मुझे लगा कि मैंने इसे उन लोगों के लिए यहां रखा है जिनके लिए कॉलबैक उपयोग का मामला लागू नहीं होता है। उदाहरण के लिए, जब मुझे स्वयं इस समस्या का सामना करना पड़ा, तो मेरे उपयोग के मामले में इसे सेट करने के बाद अद्यतन स्थिति पर एक स्विच केस शामिल था। इसलिए कॉलबैक का उपयोग करने के लिए async / प्रतीक्षा का उपयोग करना पसंद किया गया था।
कुरुकिरु

अगर मैं हमेशा कुछ स्टेट को अपडेट करना चाहता हूं और फिर अपडेट होने का इंतजार करता हूं तो क्या यह प्रभाव प्रदर्शन का हमेशा इंतजार करेगा? और अगर मैं एक के बाद एक श्रृंखला में एक से अधिक प्रतीक्षा सेटस्टेट्स डाल देता हूं, तो क्या यह प्रत्येक सेटस्टेट अपडेट के बाद प्रस्तुत करेगा? या अंतिम setState अद्यतन के बाद?
user2774480


क्या आप user2774480 से पूछ रहे हैं, मेरा मानना ​​है कि यह सभी विशिष्ट उपयोग के मामले में नीचे आता है जो यह निर्धारित करता है कि किस कार्यान्वयन का उपयोग करना है। यदि एक श्रृंखला में कई सेटस्टेट्स का उपयोग किया जाता है, तो प्रदर्शन प्रभावित होगा, और हां, यह प्रत्येक सेटस्टेट के बाद प्रस्तुत करेगा, लेकिन अगर मैं गलत हूं तो मुझे सुधारें।
kurokiiru

8

प्रतिक्रिया जीवनचक्र के तरीकों को देखें ec

मैंने यह पता लगाने के लिए कई घंटों तक काम किया कि getDerivedStateFromPropsहर के बाद कहा जाएगा setState()

😂


आपकी टिप्पणी ने मेरा दिन बचाया: D
Csaba

-1

async-await सिंटेक्स पूरी तरह से निम्नलिखित की तरह कुछ के लिए काम करता है ...

changeStateFunction = () => {
  // Some Worker..

  this.setState((prevState) => ({
  year: funcHandleYear(),
  month: funcHandleMonth()
}));

goNextMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}

goPrevMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}

-1

सीधे शब्दों में कहें - यह .setState ({data: value}) प्रकृति में अतुल्यकालिक है जिसका अर्थ है कि यह कॉल स्टैक से बाहर निकलता है और केवल कॉल स्टैक पर वापस आता है जब तक कि यह हल नहीं होता है।

जेएस में अतुल्यकालिक प्रकृति के बारे में एक स्पष्ट तस्वीर रखने के लिए कृपया इवेंट लूप के बारे में पढ़ें और इसे अपडेट करने में समय क्यों लगता है -

https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4

इसलिये -

    this.setState({data:value});
    console.log(this.state.data); // will give undefined or unupdated value

अपडेट होने में समय लगता है। उपरोक्त प्रक्रिया प्राप्त करने के लिए -

    this.setState({data:value},function () {
     console.log(this.state.data);
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.