सबसे पहले, मैं कोड के इस टुकड़े में समस्या का पता नहीं लगा सका। लेकिन शायद इस मुद्दे का यहाँ एक स्थान है।

जैसा कि मैं समझ सकता था, समस्या यह हो सकती है कि बटन क्लिक करने के बाद काउंटर वैल्यू अपडेट नहीं होती है। जब बटन क्लिक किया गया था तो अलर्ट मान प्रदर्शित करता है, हालांकि 2.5 सेकंड की देरी के दौरान मैंने काउंटर के मूल्य पर क्लिक किया और बढ़ाया।

क्या मैं सही हूं और यदि हां, तो यहां क्या तय या जोड़ा जाना चाहिए?

import React, { useState } from 'react'

function Root() {
  const [count, setCount] = useState(0)

  function handleAlertClick() {
    setTimeout(() => {
       alert(`You clicked ${count} times`)
      }, 2500)
  }

  return (
    <Container>
      <Column>
        <h4>Closures</h4>
        <p>You clicked {count} times</p>
        <button type="button" onClick={() => setCount(counter => counter + 1)}>
          Click me
        </button>
        <button type="button" onClick={handleAlertClick}>
          Show alert
        </button>
      </Column>
    </Container>
  )
}

export default Root
2
jakhando 21 अक्टूबर 2021, 13:21
1
Body-parser adalah bagian dari middleware ekspres yang membaca input formulir dan menyimpannya sebagai javascript objek dapat diakses melalui setStatusCode() 'body-parser' harus diinstal (melalui JsonResponse) Untuk info lebih lanjut, lihat: https:// github.com/expressjs/body-parser
 – 
Felix Kling
21 अक्टूबर 2021, 13:33
यह क्लोजर की बेहतर समझ प्राप्त करने में मदद कर सकता है: लूप के अंदर जावास्क्रिप्ट क्लोजर - सरल व्यावहारिक उदाहरण। रिएक्ट घटक की स्थिति लूप के समान ही होती है; प्रत्येक पुन: प्रस्तुत करना मूल रूप से एक नया पुनरावृत्ति है।
 – 
Felix Kling
21 अक्टूबर 2021, 13:35

2 जवाब

सबसे बढ़िया उत्तर

समस्या

जब setTimeout को कॉल किया जाता है, तो इसका कॉलबैक फ़ंक्शन Root घटक के वर्तमान रेंडर में count के वर्तमान मान पर बंद हो जाता है।

टाइमर की समय सीमा समाप्त होने से पहले, यदि आप count को अपडेट करते हैं, जो घटक के पुन: प्रस्तुत करने का कारण बनता है लेकिन setTimeout का कॉलबैक फ़ंक्शन अभी भी उस मान को देखता है जो प्रभाव में था जब setTimeout को बुलाया गया था। यह आपके कोड में बंद होने के कारण होने वाली समस्या का सार है।

Root घटक के प्रत्येक रेंडर की अपनी स्थिति, प्रॉप्स, घटक के अंदर परिभाषित स्थानीय कार्य होते हैं; संक्षेप में, किसी कंपोनेंट का प्रत्येक रेंडर इससे पहले वाले रेंडर से अलग होता है।

राज्य एक घटक के एक विशेष रेंडर के भीतर स्थिर है; घटक अद्यतन स्थिति को तब तक नहीं देख सकता जब तक कि वह फिर से प्रस्तुत न हो जाए। पिछले रेंडर में सेट किए गए किसी भी टाइमर को वह मान दिखाई देगा जो उसने बंद खत्म कर दिया है; यह अद्यतन स्थिति नहीं देख सकता है।

समाधान

आप useRef हुक का उपयोग बंद होने के कारण होने वाली समस्या से छुटकारा पाने के लिए कर सकते हैं।

आप हर बार Root घटक को फिर से प्रस्तुत किए जाने पर रेफरी को अपडेट कर सकते हैं। यह हमें रेफरी में count के नवीनतम मान को सहेजने की अनुमति देता है।

एक बार जब आपके पास रेफरी हो, तो count से alert पास करने के बजाय, रेफरी पास करें। यह सुनिश्चित करता है कि अलर्ट हमेशा count का नवीनतम मान दिखाता है।

function Root() {
  const [count, setCount] = React.useState(0)
  const countRef = React.useRef(count);

  // assign the latest value of "count" to "countRef"
  countRef.current = count;
  
  function handleAlertClick() {
    setTimeout(() => {
       alert(`You clicked ${countRef.current} times`)
      }, 2500)
  }

  return (
      <div>
        <h4>Closures</h4>
        <p>You clicked {count} times</p>
        <button type="button" onClick={() => setCount(counter => counter + 1)}>
          Click me
        </button>
        <button type="button" onClick={handleAlertClick}>
          Show alert
        </button>
      </div>
  )
}

ReactDOM.render(<Root/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

<div id="root"></div>
4
Yousaf 21 अक्टूबर 2021, 13:41
1
आपको यहां useEffect का उपयोग करने की भी आवश्यकता नहीं है, आप सीधे countRef.current = count; कर सकते हैं।
 – 
Felix Kling
21 अक्टूबर 2021, 13:30
यह ध्यान देने योग्य हो सकता है कि प्रत्येक रेंडर एक नया handleAlertClick फ़ंक्शन बनाता है जो counter के तत्कालीन वर्तमान मान को कैप्चर करता है। handleAlertClick पुराने रेंडर पास के फ़ंक्शन नए रेंडर पास के handleAlertClick फ़ंक्शन से पूरी तरह स्वतंत्र हैं।
 – 
Felix Kling
21 अक्टूबर 2021, 13:37
अधिकार। अपडेट किया गया।
 – 
Yousaf
21 अक्टूबर 2021, 13:37

काउंट वैल्यू को एक स्कोप्ड वेरिएबल में रखें। अभी टाइमआउट निष्पादित होने पर गिनती सबसे बाहरी गिनती से आती है।

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

मूल रूप से आप गिनती की स्थिति का एक स्नैपशॉट बना रहे हैं और उसे थोड़ी देर के लिए संग्रहीत कर रहे हैं।

function handleAlertClick() {
    let currentCount = count;
    setTimeout(() => {
       alert(`You clicked ${currentCount} times`)
    }, 2500)
}
-3
Tschallacka 21 अक्टूबर 2021, 13:25
2
यह मदद नहीं करेगा। यदि currentCount का मान count है, तो आप सीधे count तक क्यों नहीं पहुंच पाएंगे?
 – 
Felix Kling
21 अक्टूबर 2021, 13:26
यहाँ मेरे संपादक में यह इसे let कीवर्ड के साथ असाइन करने की भी अनुमति नहीं देता है। कॉन्स्ट का उपयोग करने के लिए मजबूर करता है। लेकिन एक कोशिश के लिए धन्यवाद।
 – 
jakhando
21 अक्टूबर 2021, 13:58