राज्य को अद्यतन नहीं करने पर प्रतिक्रिया सेट करें


99

इसलिए मेरे पास यह है:

let total = newDealersDeckTotal.reduce(function(a, b) {
  return a + b;
},
0);

console.log(total, 'tittal'); //outputs correct total
setTimeout(() => {
  this.setState({dealersOverallTotal: total});
}, 10);

console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1'); //outputs incorrect total

newDealersDeckTotal संख्याओं का एक मात्र [1, 5, 9]उदाहरण है, हालाँकि this.state.dealersOverallTotalसही कुल नहीं देता है लेकिन totalकरता है? मैंने यह देखने के लिए भी समय समाप्त कर दिया कि क्या यह समस्या हल हो गई है। कोई स्पष्ट या मुझे अधिक कोड पोस्ट करना चाहिए?



@ आसन चीयर्स !!
कृमि

उत्तरों में जो कहा गया है, उसके अलावा, आप स्पष्ट रूप से कॉल करने से पहले , राज्य का मान लॉग कर रहे हैं setState
फेलिक्स क्लिंग

1
@FelixKling नहीं मैं इसे सेट कर रहा हूं। इसके बाद इसे सेट करने के बाद । मैं पहले एक वैरिएबल लॉग कर रहा हूं। नहीं?
कृमि

setStateराज्य लॉग करने के बाद आपके टाइमआउट के कारण वास्तव में निष्पादित किया जाता है। मुझे लगता है कि आप डिबगिंग में जो करना चाहते थे console.log, वह समय के अंदर और setStateबाहर का हिस्सा था ।
फाबियन शुल्त्स

जवाबों:


192

setState()आमतौर पर अतुल्यकालिक है, जिसका अर्थ है कि जिस समय आप console.logराज्य में हैं, यह अभी तक अपडेट नहीं हुआ है। लॉग को setState()विधि के कॉलबैक में डालने का प्रयास करें । राज्य परिवर्तन पूरा होने के बाद इसे निष्पादित किया जाता है:

this.setState({ dealersOverallTotal: total }, () => {
  console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
}); 

2
इसके अलावा, ओपी कॉल करने से पहले राज्य के मूल्य को स्पष्ट रूप से लॉग करता है setState
फेलिक्स क्लिंग

यह मेरे लिए भी काम करता है, अतीत में मैंने इसका इस्तेमाल किया है: `this.setState ({someVar: newValue}, function () {कंसोल.लॉग (" बल अपडेट}); "लेकिन किसी कारण से यह खराब नहीं हुआ था; किसी भी अधिक, जब मैंने कोड को अद्यतन करने के लिए ऊपर काम के रूप में वर्णित किया। कोई भी विचार क्यों?
जोजकर

1
@ जोज़र को भी काम करना चाहिए, वाक्यविन्यास सही नहीं था (लापता कोष्ठक):this.setState({someVar: newValue},function(){ console.log("force update") });
फेबियन शुल्ज़

imgur.com/Ku0OjTl कृपया मुझे बताएं कि इस समस्या से छुटकारा पाने के लिए मुझे क्या करना चाहिए।
जॉनी

1
मैं इस तथ्य को पूरी तरह से भूल गया था कि यह async कॉल है और इस एक को छोड़कर सभी संभव कोड परिवर्तन किए हैं और यहां आपने मेरे मस्तिष्क को जलने से बचाया है। धन्यवाद
हेम एम

17

setState एसिंक्रोनस है। अद्यतन स्थिति प्राप्त करने के लिए आप कॉलबैक विधि का उपयोग कर सकते हैं।

changeHandler(event) {
    this.setState({ yourName: event.target.value }, () => 
    console.log(this.state.yourName));
 }

12

Async / प्रतीक्षा का उपयोग करना

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

8

setState()ऑपरेशन है अतुल्यकालिक और इसलिए अपने console.log()से पहले निष्पादित किया जाएगा setState()mutates मूल्यों और इसलिए आप परिणाम देखते हैं।

इसे हल करने के लिए, कॉलबैक फ़ंक्शन में मान लॉग करें setState(), जैसे:

setTimeout(() => {
    this.setState({dealersOverallTotal: total},
    function(){
       console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
    });
}, 10)

जावास्क्रिप्ट हमेशा तुल्यकालिक है।
संतोष सिंह

1
@ संतोशसिंह आपको गलत धारणा है। एपीआई कॉल, टाइमआउट सभी समान रूप से होते हैं।
शुभम खत्री

जैसा कि आपने ऊपर बताया कि जावास्क्रिप्ट अतुल्यकालिक है --- यह सही नहीं है। इसका मुख्य रूप से सिंक्रोनस है और ऐसे मामलों के लिए यह एसिंक्रोनस है। stackoverflow.com/questions/2035645/…
संतोष सिंह

@santoshsingh। ओह्ह यह मेरी तरफ से एक गलती थी। सही ढंग से वाक्य नहीं बना
शुभम खत्री

कॉलबैक का बहुत चालाक उपयोग यह सुनिश्चित करने के लिए कि बाद की कॉल से पहले राज्य अपडेट किया गया है!
user1204214

7

हुक के मामले में, आपको useEffectहुक का उपयोग करना चाहिए ।

const [fruit, setFruit] = useState('');

setFruit('Apple');

useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])

महान, यह उपयोग के साथ काम करता है। लेकिन इसकी आवश्यकता क्यों है?
एलेक्स 351

useEffectहर री-रेंडर पर रन करता है, और अगर ऐरे में पास किए गए आइटम स्टेट वैरिएबल सैंड चेंज किए गए हैं। इसलिए जब फल बदल गया और घटक पुन: प्रतिपादन करता है, तो वह उपयोग करेगा।
सिराज आलम

मैं उपयोग के बाहर सेटफ्रूट और कंसोल.लॉग फल चलाता हूं, और यह नहीं बदलता है। : /
alex351

4

सेटस्टेट प्रतिक्रिया में अतुल्यकालिक है, इसलिए कंसोल में अपडेट की गई स्थिति को देखने के लिए कॉलबैक का उपयोग करें जैसा कि नीचे दिखाया गया है (सेटबैक अपडेट के बाद कॉलबैक फ़ंक्शन निष्पादित होगा)

यहाँ छवि विवरण दर्ज करें

नीचे दी गई विधि "अनुशंसित नहीं है" लेकिन समझने के लिए, यदि आप सीधे राज्य को म्यूट करते हैं तो आप अद्यतन राज्य को अगली पंक्ति में देख सकते हैं। मैं दोहराता हूं कि यह "अनुशंसित नहीं" है

यहाँ छवि विवरण दर्ज करें


आपको लगता है कि यह वह है, आपको सीधे वेरिएबल सेट करना होगा
Notacorn


1

मेरे पास कुछ जटिल कोड के साथ एक ही स्थिति थी, और मौजूदा सुझावों में से कुछ भी मेरे लिए काम नहीं करता था।

मेरी समस्या यह थी कि setStateकॉलबैक फंक से हो रहा था, घटकों में से एक द्वारा जारी किया गया था। और मेरा संदेह यह है कि कॉल समकालिक रूप से हो रहा था, जिसने setStateराज्य को स्थापित करने से रोक दिया था।

सीधे शब्दों में कहें तो मेरे पास कुछ ऐसा है:

render() {
    <Control
        ref={_ => this.control = _}
        onChange={this.handleChange}
        onUpdated={this.handleUpdate} />
}

handleChange() {
    this.control.doUpdate();
}

handleUpdate() {
    this.setState({...});
}

जिस तरह से मैं "ठीक" किया था यह डाल करने के लिए था doUpdate()में setTimeoutइस तरह:

handleChange() {
    setTimeout(() => { this.control.doUpdate(); }, 10);
}

आदर्श नहीं है, लेकिन अन्यथा यह एक महत्वपूर्ण प्रभावकारी होगा।


इससे मेरी समस्या हल हो गई, लेकिन मैंने इसके बजाय सेटस्टेट () के अंदर सेटस्टेट () डाल दिया। धन्यवाद!
थरगेंदिआद

0

जब राज्य में कई बार प्रतिक्रिया होती है तो मेरे पास एक मुद्दा था (यह हमेशा डिफ़ॉल्ट स्थिति का उपयोग करता है)। इस प्रतिक्रिया के बाद / github मुद्दे ने मेरे लिए काम किया

const [state, setState] = useState({
  foo: "abc",
  bar: 123
});

// Do this!
setState(prevState => {
  return {
    ...prevState,
    foo: "def"
  };
});
setState(prevState => {
  return {
    ...prevState,
    bar: 456
  };
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.