useSyncExternalStore मुळे एखादा component React च्या बाहेर असलेल्या डेटाला वाचू शकतो, ज्यामुळे concurrent rendering मुळे येणारे visual glitches टाळता येतात. हे useEffect वापरून बाह्य व्हॅल्यूज स्थानिक state मध्ये आणण्याच्या जुन्या पद्धतीला रिप्लेस करते, ज्या पद्धतीमुळे "tearing" होऊ शकते – म्हणजेच एकाच render दरम्यान UI चे काही भाग वेगवेगळे व्हॅल्यूज दाखवू शकतात.
Concurrency मध्ये जुनी पद्धत का बिघडते
React 18 पूर्वी, सामान्य पद्धत अशी होती:
const [value, setValue] = useState(initial);
useEffect(() => {
const unsubscribe = externalSource.subscribe(v => setValue(v));
return unsubscribe;
}, []);
Effect component render झाल्यानंतर रन होते. जेव्हा React चा concurrent renderer render थांबवण्याचा, रद्द करण्याचा किंवा पुन्हा प्ले करण्याचा निर्णय घेतो, तेव्हा effect ही UI च्या तुलनेत वेगळ्या वेळी फायर होऊ शकते जी state वाचते. याचा परिणाम mismatch मध्ये होतो: एका component ने जुनी व्हॅल्यू वाचली असेल, तर दुसऱ्याने नवीन, आणि स्क्रीनवर काही क्षणांसाठी विसंगत (inconsistent) डेटा दिसतो. ही "tearing" पूर्णपणे synchronous जगात निरुपद्रवी आहे, परंतु जेव्हा React एकाच वेळी UI चे अनेक व्हर्जन रेंडर करते, तेव्हा ती एक दृश्य दोष (visible bug) बनते.
useSyncExternalStore ही समस्या कशी सोडवते
या hook साठी दोन callbacks आवश्यक आहेत:
- subscribe – एक listener रजिस्टर करते आणि तो काढून टाकण्यासाठी एक function परत करते.
- getSnapshot – बाह्य source ची सध्याची व्हॅल्यू परत करते.
React component mount झाल्यावर subscribe कॉल करते आणि unmount झाल्यावर ते काढून टाकते. प्रत्येक render दरम्यान ते getSnapshot कॉल करते आणि खात्री देते की एकाच external store चा वापर करणारे सर्व components अगदी तोच snapshot वाचतात. कारण ही प्रक्रिया render phase च्या आत घडते, renderer संपूर्ण tree मध्ये updates समन्वयित (coordinate) करू शकतो, ज्यामुळे tearing टाळता येते.
Zustand आणि Redux सारख्या libraries आधीच त्यांच्या stores साठी या hook चा वापर करतात, म्हणूनच ते React 18 च्या concurrent features सोबत सहजपणे काम करतात.
Hook चुकीच्या पद्धतीने वापरू नये यासाठीचे नियम
- फक्त component ला आवश्यक तेच परत करा – मोठा object असल्यास React ला प्रत्येक update वेळी खोलवर (deep) स्ट्रक्चर्सची तुलना करावी लागते. एक छोटा (narrow) snapshot बदल शोधणे सोपे आणि स्वस्त ठेवतो.
- Referential identity जपा – जर बाह्य व्हॅल्यू बदलली नसेल, तर getSnapshot ने तोच object reference परत केला पाहिजे. प्रत्येक वेळी नवीन object परत केल्यास infinite render loop सुरू होऊ शकतो, कारण React ला प्रत्येक render मध्ये बदल दिसतो.
- फक्त external sources साठी मर्यादित ठेवा – स्थानिक component state साठी
useStateकिंवाuseReducerवापरावे. केवळ अंतर्गत (internal) व्हॅल्यूजसाठी external-store hook वापरल्याने अनावश्यक गुंतागुंत वाढते.
useSyncExternalStore कधी वापरावे
- Browser APIs wrap करण्यासाठी (window size, network-online status, media queries).
- React बद्दल माहिती नसलेले plain JavaScript store कनेक्ट करण्यासाठी.
- Prop-drilling च्या जागी एक global read-only source वापरण्यासाठी ज्याला अनेक components subscribe करू शकतात.
प्रतिवाद (The counter-argument)
साध्या आणि क्वचितच बदलणाऱ्या डेटासाठी useState + useEffect ही पद्धत अजूनही काम करते, विशेषतः जेव्हा एखादे application concurrent features सक्षम करत नाही. ही एक lower-level पद्धत आहे जी काही developers ना समजायला सोपी वाटते कारण subscription logic स्पष्टपणे effect मध्ये असते. तथापि, याचा तोटा म्हणजे concurrent rendering सुरू केल्यावर tearing चा धोका निर्माण होतो. ज्या प्रकल्पांमध्ये आधीच React 18 च्या नवीन क्षमता वापरल्या जात आहेत, त्यांच्यासाठी useSyncExternalStore ची अतिरिक्त सुरक्षा थोड्या वाढीव boilerplate पेक्षा जास्त महत्त्वाची आहे.
पुढे काय पाहावे
- तुमच्या store चा getSnapshot एक stable reference परत करतोय याची खात्री करा; development दरम्यान reference चा
console.logकेल्यास चुकून नवीन object तयार होत आहे का हे समजेल. - Subscription function हलके (lightweight) ठेवा – जड कामे (heavy work) बाह्य source मध्ये व्हायला हवीत, React ला पास केलेल्या callback मध्ये नाही.
- React च्या concurrent mode मध्ये components टेस्ट करा (उदा.
ReactDOM.createRootसोबतactवापरून) जेणेकरून कोणताही tearing दिसत नाही याची खात्री होईल.
एक live demo या hook चे कार्य दाखवतो, जो React च्या बाहेर साठवलेला एक साधा counter sync करतो आणि कोणत्याही visual glitches शिवाय अनेक components अपडेट करतो. डेमो https://usesyncexternalstore.vercel.app/ वर उपलब्ध आहे. सोर्स कोड GitHub वर आहे, आणि एक सविस्तर लेख अंमलबजावणीचे (implementation) तपशील स्पष्ट करतो.
Takeaway: ज्या जगात React UI चे काही भाग क्रमाने न येता (out of order) रेंडर करू शकते, तिथे useSyncExternalStore हा बाह्य डेटा आणि component rendering मधील एक विश्वसनीय दुवा आहे. हे visual consistency राखते, global stores पर्यंत विस्तारते आणि लोकप्रिय state-management libraries मध्ये आधीच समाविष्ट आहे. जिथे तुम्हाला non-React state वाचण्याची गरज आहे तिथे याचा वापर करा, आणि त्याचे पूर्ण फायदे मिळवण्यासाठी snapshots लहान आणि स्थिर ठेवा.
