"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > प्रतिक्रिया: बासी समापन

प्रतिक्रिया: बासी समापन

2024-09-02 को प्रकाशित
ब्राउज़ करें:830

इस पोस्ट में, मैं दिखाऊंगा कि यूज़स्टेट हुक रिएक्ट ऐप में क्लोजर कैसे बनाया जाता है।

मैं यह नहीं समझाऊंगा कि समापन क्या है, क्योंकि इस विषय के बारे में कई संसाधन हैं और मैं दोहराव नहीं करना चाहता। मैं @imranabdulmalik के इस लेख को पढ़ने की सलाह देता हूं।

संक्षेप में, एक क्लोजर है (मोज़िला से):

...किसी फ़ंक्शन का संयोजन उसके आस-पास की स्थिति (शब्दावली वातावरण) के संदर्भ में एक साथ बंडल (संलग्न) किया गया है। दूसरे शब्दों में, एक क्लोजर आपको आंतरिक फ़ंक्शन से बाहरी फ़ंक्शन के दायरे तक पहुंच प्रदान करता है। जावास्क्रिप्ट में, जब भी कोई फ़ंक्शन बनाया जाता है, तो फ़ंक्शन निर्माण के समय पर क्लोजर बनाए जाते हैं।

अगर आप शब्द शब्दावली पर्यावरण से परिचित नहीं हैं, आप @soumyadey का यह लेख या वैकल्पिक रूप से यह लेख पढ़ सकते हैं।

समस्या

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

पीओसी

मैंने एक डेमो रिएक्ट एप्लिकेशन बनाया है जिसका मुख्य लक्ष्य एक काउंटर (राज्य से संबंधित) को बढ़ाना है जिसे सेटटाइमआउट विधि के कॉलबैक में बंद किया जा सकता है।

संक्षेप में, यह ऐप यह कर सकता है:

  • काउंटर का मूल्य दिखाएं
  • काउंटर में 1 की वृद्धि
  • पांच सेकंड के बाद काउंटर को 1 बढ़ाने के लिए टाइमर प्रारंभ करें।
  • काउंटर में 10 की वृद्धि

निम्न चित्र में, यह ऐप की प्रारंभिक यूआई स्थिति को शून्य के काउंटर के साथ दिखाता है।

React: stale closure

हम तीन चरणों में काउंटर को बंद करने का अनुकरण करेंगे:

  1. काउंटर 1 से बढ़ रहा है

React: stale closure

  1. पांच सेकंड के बाद 1 की वृद्धि के लिए टाइमर शुरू किया जा रहा है

React: stale closure

  • टाइमआउट ट्रिगर से पहले 10 की वृद्धि React: stale closure

5 सेकंड के बाद, काउंटर का मान 2 है।

React: stale closure

काउंटर का अपेक्षित मूल्य 12 होना चाहिए, लेकिन हमें 2 मिलता है।

ऐसा होने का कारण यह है कि हमने setTimeout को दिए गए कॉलबैक में काउंटर को बंद कर दिया है और जब टाइमआउट ट्रिगर होता है तो हम काउंटर को उसके से शुरू करके सेट करते हैं पुराना मान (वह 1 था).

setTimeout(() => {
        setLogs((l) => [...l, `You closed counter with value: ${counter}\n and now I'll increment by one. Check the state`])
        setTimeoutInProgress(false)
        setStartTimeout(false)
        setCounter(counter   1)
        setLogs((l) => [...l, `Did you create a closure of counter?`])

      }, timeOutInSeconds * 1000);

ऐप घटक के पूर्ण कोड का अनुसरण किया जा रहा है।

function App() {
  const [counter, setCounter] = useState(0)
  const timeOutInSeconds: number = 5
  const [startTimeout, setStartTimeout] = useState(false)
  const [timeoutInProgress, setTimeoutInProgress] = useState(false)
  const [logs, setLogs] = useState>([])

  useEffect(() => {
    if (startTimeout && !timeoutInProgress) {
      setTimeoutInProgress(true)
      setLogs((l) => [...l, `Timeout scheduled in ${timeOutInSeconds} seconds`])
      setTimeout(() => {
        setLogs((l) => [...l, `You closed counter with value: ${counter}\n and now I'll increment by one. Check the state`])
        setTimeoutInProgress(false)
        setStartTimeout(false)
        setCounter(counter   1)
        setLogs((l) => [...l, `Did you create a closure of counter?`])

      }, timeOutInSeconds * 1000);
    }
  }, [counter, startTimeout, timeoutInProgress])

  function renderLogs(): React.ReactNode {
    const listItems = logs.map((log, index) =>
      
  • {log}
  • ); return
      {listItems}
    ; } function updateCounter(value: number) { setCounter(value) setLogs([...logs, `The value of counter is now ${value}`]) } function reset() { setCounter(0) setLogs(["reset done!"]) } return (

    Closure demo


    Counter value: {counter}


    Follow the istructions to create a closure of the state variable counter

    1. Set the counter to preferred value
    2. Start a timeout and wait for {timeOutInSeconds} to increment the counter (current value is {counter})
    3. Increment by 10 the counter before the timeout

    { renderLogs() }
    ); } export default App;

    समाधान

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

    इसलिए हम ऐप घटक में जोड़ते हैं:

    const currentCounter = useRef(counter)
    

    फिर हम नीचे दिखाए गए अनुसार सेटटाइमआउट के कॉलबैक को संशोधित करेंगे:

    setTimeout(() => {
            setLogs((l) => [...l, `You closed counter with value: ${currentCounter.current}\n and now I'll increment by one. Check the state`])
            setTimeoutInProgress(false)
            setStartTimeout(false)
            setCounter(currentCounter.current   1)
            setLogs((l) => [...l, `Did you create a closure of counter?`])
    
          }, timeOutInSeconds * 1000);
    

    हमारे कॉलबैक को काउंटर वैल्यू को पढ़ने की आवश्यकता है क्योंकि हम इसे बढ़ाने के लिए पहले वर्तमान मूल्य को लॉग करते हैं।

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

    seCounter(c => c   1)
    

    संसाधन

    • दिमित्री पाव्लुटिन रिएक्ट हुक का उपयोग करते समय पुराने बंद होने से सावधान रहें
    • इमरान अब्दुलमलिक जावास्क्रिप्ट में क्लोजर में महारत हासिल करना: एक व्यापक गाइड
    • जावास्क्रिप्ट में केयूर पारलकर लेक्सिकल स्कोप - शुरुआती गाइड
    • रिएक्ट में सौविक पॉल बासी क्लोजर
    • सौम्या डे जावास्क्रिप्ट में लेक्सिकल स्कोप और क्लोजर को समझ रही हैं
    • सुबाष महापात्रा स्टैकओवरफ्लो
    विज्ञप्ति वक्तव्य यह लेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/animusna/react-stale-closure-81a?1 यदि कोई उल्लंघन है, तो कृपया इसे हटाने के लिए [email protected] से संपर्क करें।
    नवीनतम ट्यूटोरियल अधिक>

    चीनी भाषा का अध्ययन करें

    अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

    Copyright© 2022 湘ICP备2022001581号-3