अधिकांश फ्रंटएंड कोड एसिंक्रोनस कार्य को एक ही रूप में देखता है। आप एक Promise शुरू करते हैं, उसके रिज़ॉल्व होने का इंतज़ार करते हैं, परिणाम को लोकल स्टेट में डालते हैं, और फ्रेमवर्क को diff को reconcile करने देते हैं। यह पैटर्न लुभावना है क्योंकि यह हर जगह काम करता है: एक REST कॉल, एक फॉर्म सबमिशन, या एक WebSocket मैसेज। वे सभी एक ही useEffect या इवेंट हैंडलर में आते हैं, सभी setState के माध्यम से पाइपलाइन किए जाते हैं, और सभी एक जैसे async प्लंबिंग की तरह दिखते हैं। यह एकरूपता एक जाल है। एक वास्तविक एप्लिकेशन में, सभी async कार्य एक जैसे नहीं होते हैं। ऐसा दिखावा करना कि वे एक जैसे हैं, आपके UI कंपोनेंट्स को अनजाने में डेटा आर्किटेक्ट्स बना देता है, जिन्हें useEffect हुक्स और किस्मत के भरोसे जोड़कर बनाया गया है।
एसिंक्रोनस ऑपरेशन्स वास्तव में तीन अलग-अलग प्रजातियों में आते हैं। प्रत्येक का समय, कैशिंग और ओनरशिप के साथ अलग संबंध होता है। उन्हें अलग पहचानना सीखना ही फ्रंटएंड को तेज़, सही और व्यवस्थित रखता है।
Queries: एक पते के साथ तथ्य
एक क्वेरी केवल एक fetch नहीं है। यह एक पहचानने योग्य तथ्य के लिए अनुरोध है। आप /user/123 मांग रहे हैं, न कि "कुछ यूजर डेटा"। यह अंतर महत्वपूर्ण है क्योंकि पहचान (identity) ही कैशिंग को संभव बनाती है। यदि एक ही स्क्रीन पर दो कंपोनेंट्स को एक ही यूजर रिकॉर्ड की आवश्यकता है, तो उन्हें एक ही उत्तर साझा करना चाहिए। जब प्रत्येक कंपोनेंट useState में अपनी स्थानीय प्रति (local copy) रखता है, तो आप अपनी सच्चाई को खंडित कर देते हैं। हेडर में अवतार और साइडबार में नाम अलग-अलग हो जाते हैं क्योंकि उन्हें अलग-अलग समय पर फेच किया गया था, या एक विफल हो गया जबकि दूसरा सफल रहा।
एक क्वेरी को एक एक्शन के बजाय एक रिसोर्स के रूप में सोचें। इसमें एक कैश की (cache key), एक फ्रेशनेस पॉलिसी और एक लाइफसाइकिल होती है जो किसी भी एकल कंपोनेंट से अधिक समय तक रहती है। एक अच्छी तरह से निर्मित क्वेरी लेयर समझती है कि /projects?page=2 को पढ़ना /projects?page=3 को पढ़ने से अलग है। प्रत्येक URL और पैरामीटर सेट एक पता (address) बनाता है, और उस पते पर डेटा पुराना (stale), ताज़ा (fresh), या गायब हो सकता है। UI को यह हिसाब-किताब नहीं रखना चाहिए। इसे डेटा लेयर से user:123 मांगना चाहिए और एक स्नैपशॉट प्राप्त करना चाहिए। वह स्नैपशॉट दो सेकंड पहले सर्वर से आया था या दो मिलीसेकंड पहले कैश से, इससे कंपोनेंट को कोई लेना-देना नहीं होना चाहिए।
इसका व्यावहारिक परिणाम तुरंत सामने आता है। जब आप हर रीड (read) को कंपोनेंट के भीतर एक इम्पैरेटिव फेच (imperative fetch) के रूप में देखते हैं, तो आप डुप्लीकेशन हटाना (deduplication) खो देते हैं। आप बैकग्राउंड रिफ्रेश खो देते हैं। आप बैकग्राउंड में डेटा को वैलिडेट करते समय तुरंत कैश किया गया डेटा दिखाने की क्षमता खो देते हैं। एक क्वेरी आपके UI ट्री के बाहर एक घर की हकदार है।
Mutations: दुनिया को बदलना
यदि क्वेरीज़ दुनिया के बारे में पूछती हैं, तो म्यूटेशन उसे बदलते हैं। वास्तविक नेटवर्क अनुरोध—POST, PUT, या DELETE—आमतौर पर आसान हिस्सा होता है। कठिन हिस्सा वह सब है जो सर्वर के "OK" कहने के बाद होता है।
मान लीजिए कि एक यूजर अपना डिस्प्ले नाम अपडेट करता है। म्यूटेशन अपने आप में एक एकल अनुरोध है। लेकिन इसका प्रभाव (blast radius) हर जगह होता है। प्रोफाइल पेज पर पुराना नाम है। नेविगेशन बार पुराना नाम दिखाता है। कमेंट हिस्ट्री उसका संदर्भ दे सकती है। यदि आपका म्यूटेशन कोड एक स्थानीय isLoading फ्लैग को टॉगल करने और फिर स्टेट के एक हिस्से को अपडेट करने के अलावा कुछ नहीं करता है, तो आपका एप्लिकेशन अब खुद से झूठ बोल रहा है। UI के कुछ हिस्से दिखावा करते हैं कि बदलाव हो गया है। अन्य को पता ही नहीं चलता कि कुछ बदला भी है।
एक म्यूटेशन को डेटा ग्राफ पर अपने प्रभाव की घोषणा करनी चाहिए। इसे सिस्टम को बताना चाहिए कि कौन सी क्वेरीज़ अब अमान्य (invalid) हैं, किन कैश कीज़ को फिर से फेच (refetch) करने की आवश्यकता है, और कौन से संबंध बदल गए हैं। यह मौलिक रूप से एक क्वेरी से अलग है। एक क्वेरी रीड-ओनली और साझा करने योग्य होती है। एक म्यूटेशन राइट-केंद्रित होता है और मौजूदा कैश को नष्ट कर देता है। उन्हें एक ही एब्स्ट्रैक्शन में मिला देने का मतलब है कि डेवलपर्स अंततः रैंडम कंपोनेंट्स के अंदर मैन्युअल रूप से refetch() कॉल करने लगते हैं, या इससे भी बदतर, लोकल स्टेट को सर्वर के साथ सिंक करने के लिए पूरे ट्री में useEffect हुक्स का उपयोग करने लगते हैं।
ओनरशिप मॉडल भी अलग है। क्वेरीज़ का स्वामित्व आमतौर पर कैश के पास होता है। एक म्यूटेशन उस यूजर एक्शन द्वारा स्वामित्व में होता है जिसने इसे ट्रिगर किया है। इसमें एक पेंडिंग स्टेट, एक एरर स्टेट और संभावित रूप से एक ऑप्टिमिस्टिक वैल्यू होती है जिसे रोल
