बहुतेक frontend कोड asynchronous काम एकाच स्वरूपाचे समजतो. तुम्ही एक Promise सुरू करता, तो resolve होण्याची वाट पाहता, निकाल local state मध्ये टाकता आणि framework ला diff reconcile करू देता. ही पद्धत मोहक वाटते कारण ती सर्वत्र काम करते: REST call, form submission, किंवा WebSocket message. हे सर्व एकाच useEffect किंवा event handler मध्ये येतात, setState द्वारे पाइपलाइन केले जातात आणि सर्व काही एकाच प्रकारचे async प्लंबिंग असल्यासारखे वाटते. ही एकरूपता एक सापळा आहे. वास्तविक ॲप्लिकेशनमध्ये, सर्व async कामे सारखी नसतात. तसे भासणे तुमच्या UI components ला useEffect hooks आणि नशिबाच्या जोरावर जोडलेले 'अनावधानाने बनलेले डेटा आर्किटेक्ट्स' बनवते.

Async ऑपरेशन्स प्रत्यक्षात तीन वेगवेगळ्या प्रजातींमध्ये विभागले जातात. प्रत्येकाचा वेळ (time), caching आणि ownership सोबत वेगळा संबंध असतो. त्यांना एकमेकांपासून वेगळे ओळखायला शिकणे हेच frontend ला वेगवान, अचूक आणि सुव्यवस्थित ठेवते.

Queries: Facts with an Address

Query म्हणजे केवळ fetch नाही. ती एका ओळखण्यायोग्य तथ्यासाठी (fact) केलेली विनंती आहे. तुम्ही /user/123 साठी विचारत आहात, "काही युजर डेटा" साठी नाही. हा फरक महत्त्वाचा आहे कारण identity मुळेच caching शक्य होते. जर एकाच स्क्रीनवरील दोन componentsना एकाच युजर रेकॉर्डची गरज असेल, तर त्यांनी एकच उत्तर शेअर केले पाहिजे. जेव्हा प्रत्येक component useState मध्ये स्वतःची स्थानिक प्रत (local copy) ठेवते, तेव्हा तुम्ही तुमच्या सत्याचे तुकडे करता. हेडरमधील अवतार आणि साइडबारमधील नाव एकमेकांपासून वेगळे होऊ शकतात कारण ते वेगवेगळ्या वेळी fetch केले गेले होते, किंवा एक यशस्वी झाले तर दुसरे अयशस्वी झाले.

Query ला एक कृती (action) म्हणून नाही, तर एक संसाधन (resource) म्हणून पहा. त्याला एक cache key, freshness policy आणि असे lifecycle असते जे कोणत्याही सिंगल component पेक्षा जास्त काळ टिकते. एक सुव्यवस्थित query layer हे समजून घेते की /projects?page=2 वाचणे हे /projects?page=3 वाचण्यापेक्षा वेगळे आहे. प्रत्येक URL आणि parameter सेट एक पत्ता (address) तयार करतो, आणि त्या पत्त्यावरील डेटा जुना (stale), ताजा (fresh) किंवा गहाळ असू शकतो. UI ने हे bookkeeping करण्याची गरज नाही. त्याने data layer कडे user:123 साठी विचारले पाहिजे आणि एक snapshot प्राप्त केला पाहिजे. तो snapshot दोन सेकंदांपूर्वी सर्व्हरकडून आला की दोन मिलीसेकंदपूर्वी कॅशमधून आला, याच्याशी component ला काहीही देणेघेणे नसते.

याचे व्यावहारिक परिणाम तात्काळ दिसून येतात. जेव्हा तुम्ही प्रत्येक 'read' ला component च्या आत एक imperative fetch म्हणून वागवता, तेव्हा तुम्ही deduplication गमावता. तुम्ही background refresh गमावता. बॅकग्राउंडमध्ये व्हॅलिडेट करत असताना कॅश केलेला डेटा त्वरित दाखवण्याची क्षमता तुम्ही गमावता. Query ला तुमच्या UI tree च्या बाहेर एक घर मिळायला हवे.

Mutations: Changing the World

जर Queries जगाबद्दल विचारत असतील, तर Mutations ते बदलतात. प्रत्यक्ष नेटवर्क विनंती—POST, PUT, किंवा DELETE—सहसा सोपा भाग असतो. कठीण भाग म्हणजे सर्व्हर "OK" म्हटल्यानंतर घडणाऱ्या सर्व गोष्टी.

समजा एखाद्या वापरकर्त्याने त्यांचे display name अपडेट केले. Mutation स्वतः एक सिंगल रिक्वेस्ट आहे. पण त्याचा परिणाम (blast radius) सर्वत्र होतो. प्रोफाइल पेजवर जुने नाव आहे. नेव्हिगेशन बारमध्ये जुने नाव दिसते. कमेंट हिस्ट्रीमध्ये त्याचा संदर्भ असू शकतो. जर तुमचा mutation कोड फक्त एक स्थानिक isLoading फ्लॅग टॉगल करतो आणि नंतर एक state अपडेट करतो, तर तुमचे ॲप्लिकेशन आता स्वतःशीच खोटे बोलत आहे. UI चे काही भाग बदल झाला आहे असे भासवतात, तर इतरांना काहीच बदल झाल्याचे माहित नसते.

Mutation ने data graph वर होणाऱ्या त्याच्या प्रभावाची घोषणा केली पाहिजे. त्याने सिस्टमला सांगायला हवे की आता कोणत्या queries invalid आहेत, कोणत्या cached keys पुन्हा fetch करण्याची गरज आहे आणि कोणते संबंध (relationships) बदलले आहेत. हे Query पेक्षा मूलभूतपणे वेगळे आहे. Query ही read-only आणि shareable असते. Mutation ही write-focused असते आणि अस्तित्वात असलेल्या कॅशेसाठी destructive असते. त्यांना एकाच abstraction मध्ये एकत्र करणे म्हणजे डेव्हलपर्सना यादृच्छिक components मध्ये मॅन्युअली refetch() कॉल करावे लागतात, किंवा त्याहून वाईट, स्थानिक state ला सर्व्हरशी पुन्हा सुसंगत (sync) करण्यासाठी संपूर्ण tree मध्ये useEffect hooks पसरवावे लागतात.

Ownership model देखील वेगळा आहे. Queries सहसा cache द्वारे नियंत्रित केल्या जातात. Mutation हे तिला ट्रिगर करणाऱ्या युजर ॲक्शनद्वारे नियंत्रित केले जाते. त्याला एक pending state, एक error state आणि संभाव्यतः एक optimistic value असते ज्याला roll