useSyncExternalStore કમ્પોનન્ટને React ની બહાર રહેલા ડેટાને વાંચવાની મંજૂરી આપે છે, જેનાથી કોન્કરન્ટ રેન્ડરિંગ (concurrent rendering) દ્વારા ઉભા થઈ શકે તેવા વિઝ્યુઅલ ગ્લિચિસ (visual glitches) નું જોખમ રહેતું નથી. તે useEffect દ્વારા એક્સટર્નલ વેલ્યુઝને લોકલ સ્ટેટમાં લાવવાની જૂની પદ્ધતિનું સ્થાન લે છે, જે પદ્ધતિ "tearing" – એટલે કે એક જ રેન્ડર દરમિયાન UI ના અલગ-અલગ ભાગો અલગ-અલગ વેલ્યુ બતાવે છે – જેવી સમસ્યાઓ ઊભી કરી શકે છે.

કોન્કરન્સી (concurrency) હેઠળ જૂની પદ્ધતિ કેમ નિષ્ફળ જાય છે

React 18 પહેલા, સામાન્ય રીત આ હતી:

const [value, setValue] = useState(initial);
useEffect(() => {
  const unsubscribe = externalSource.subscribe(v => setValue(v));
  return unsubscribe;
}, []);

ઇફેક્ટ (effect) કમ્પોનન્ટ રેન્ડર થયા પછી ચાલે છે. જ્યારે React નું કોન્કરન્ટ રેન્ડરર રેન્ડરિંગને રોકવા (pause), રદ કરવા (abort), અથવા ફરીથી ચલાવવાનો (replay) નિર્ણય લે છે, ત્યારે ઇફેક્ટ સ્ટેટ વાંચતા UI કરતા અલગ સમયે ફાયર થઈ શકે છે. પરિણામે મિસમેચ (mismatch) થાય છે: એક કમ્પોનન્ટે જૂની વેલ્યુ વાંચી હોય, બીજાએ નવી, અને સ્ક્રીન ક્ષણિક રીતે અસંગત ડેટા બતાવે છે. આ "tearing" શુદ્ધ રીતે સિંક્રનસ (synchronous) દુનિયામાં નુકસાનકારક નથી, પરંતુ જ્યારે React સમાંતર રીતે (in parallel) UI ના મલ્ટિપલ વર્ઝન રેન્ડર કરે છે, ત્યારે તે એક દેખીતી ભૂલ (bug) બની જાય છે.

useSyncExternalStore સમસ્યા કેવી રીતે ઉકેલે છે

આ હૂક માટે બે કોલબેક્સ (callbacks) જરૂરી છે:

  • subscribe – લિસનર રજીસ્ટર કરે છે અને તેને દૂર કરવા માટે એક ફંક્શન રિટર્ન કરે છે.
  • getSnapshot – એક્સટર્નલ સોર્સની વર્તમાન વેલ્યુ રિટર્ન કરે છે.

જ્યારે કમ્પોનન્ટ માઉન્ટ (mount) થાય ત્યારે React subscribe ને કોલ કરે છે અને અનમાઉન્ટ (unmount) વખતે તેને ડિસ્પોઝ (dispose) કરે છે. દરેક રેન્ડર દરમિયાન તે getSnapshot ને ઇનવોક કરે છે અને ખાતરી આપે છે કે સમાન એક્સટર્નલ સ્ટોરનો ઉપયોગ કરતા તમામ કમ્પોનન્ટ્સ બરાબર એક જ સ્નેપશોટ (snapshot) વાંચે છે. કારણ કે રીડિંગ રેન્ડર ફેઝની અંદર થાય છે, રેન્ડરર આખા ટ્રી (tree) માં અપડેટ્સનું સંકલન કરી શકે છે, જેનાથી tearing દૂર થાય છે.

Zustand અને Redux જેવી લાઇબ્રેરીઓ પહેલેથી જ તેમના સ્ટોર્સને આ હૂક સાથે રેપ (wrap) કરે છે, તેથી જ તેઓ React 18 ના કોન્કરન્ટ ફીચર્સ સાથે સીધા જ કામ કરે છે.

હૂકને ખોટી રીતે વર્તતા અટકાવવા માટેના નિયમો

  1. માત્ર તે જ રિટર્ન કરો જે કમ્પોનન્ટને જરૂર હોય – એક મોટું ઓબ્જેક્ટ દરેક અપડેટ પર React ને ઊંડા સ્ટ્રક્ચર્સ (deep structures) સરખાવવા માટે મજબૂર કરે છે. એક નાનો (narrow) સ્નેપશોટ ચેન્જ ડિટેક્શનને સસ્તું (cheap) રાખે છે.
  2. રેફરન્શિયલ આઈડેન્ટિટી (referential identity) જાળવી રાખો – જો એક્સટર્નલ વેલ્યુ બદલાઈ નથી, તો getSnapshot એ સમાન ઓબ્જેક્ટ રેફરન્સ રિટર્ન કરવો જોઈએ. દરેક કોલ પર નવું ઓબ્જેક્ટ રિટર્ન કરવાથી ઇન્ફિનિટ રેન્ડર લૂપ (infinite render loop) ટ્રિગર થાય છે કારણ કે React દરેક રેન્ડર પર ફેરફાર જુએ છે.
  3. ઉપયોગ માત્ર એક્સટર્નલ સોર્સ સુધી મર્યાદિત રાખો – લોકલ કમ્પોનન્ટ સ્ટેટ useState અથવા useReducer માં હોવું જોઈએ. શુદ્ધ રીતે ઇન્ટરનલ વેલ્યુઝ માટે એક્સટર્નલ-સ્ટોર હૂકનો ઉપયોગ કરવાથી બિનજરૂરી ઇન્ડિરેક્શન (indirection) ઉમેરાય છે.

useSyncExternalStore નો ઉપયોગ ક્યારે કરવો

  • બ્રાઉઝર APIs (window size, network-online status, media queries) ને રેપ કરવા માટે.
  • એવા પ્લેન JavaScript સ્ટોરને કનેક્ટ કરવા માટે જે React વિશે જાણતું નથી.
  • પ્રોપ-ડ્રિલિંગ (prop-drilling) ને ગ્લોબલ રીડ-ઓન્લી સોર્સ સાથે બદલવા માટે જેના પર ઘણા કમ્પોનન્ટ્સ સબ્સ્ક્રાઇબ કરે છે.

વિરોધી દલીલ (The counter-argument)

useState + useEffect પદ્ધતિ હજુ પણ સરળ અને ભાગ્યે જ બદલાતા ડેટા માટે કામ કરે છે, ખાસ કરીને જ્યારે એપ્લિકેશનમાં કોન્કરન્ટ ફીચર્સ ઇનેબલ ન હોય. તે એક લો-લેવલ એપ્રોચ છે જેને કેટલાક ડેવલપર્સ સમજવામાં સરળ માને છે કારણ કે સબ્સ્ક્રિપ્શન લોજિક સ્પષ્ટપણે ઇફેક્ટમાં રહેલું હોય છે. જોકે, તેની સામેનો નુકસાન એ છે કે એકવાર કોન્કરન્ટ રેન્ડરિંગ ચાલુ થાય પછી tearing નું જોખમ રહે છે. જે પ્રોજેક્ટ્સ પહેલેથી જ React 18 ની નવી ક્ષમતાઓનો ઉપયોગ કરે છે, તેમના માટે useSyncExternalStore ની વધારાની સુરક્ષા વધારાના બોઈલરપ્લેટ (boilerplate) કરતા વધુ મહત્વની છે.

આગળ શું ધ્યાન રાખવું

  • ખાતરી કરો કે તમારા સ્ટોરનું getSnapshot એક સ્ટેબલ રેફરન્સ રિટર્ન કરે છે; ડેવલપમેન્ટ દરમિયાન રેફરન્સનું ઝડપી console.log અજાણતા ઓબ્જેક્ટ રીક્રિએશનને ખુલ્લું પાડી શકે છે.
  • સબ્સ્ક્રિપ્શન ફંક્શનને લાઇટવેઇટ (lightweight) રાખો – ભારે કામ એક્સટર્નલ સોર્સની અંદર થવું જોઈએ, React ને પાસ કરવામાં આવેલા કોલબેકમાં નહીં.
  • કોઈ tearing દેખાતી નથી તેની ખાતરી કરવા માટે React ના કોન્કરન્ટ મોડ હેઠળ કમ્પોનન્ટ્સનું ટેસ્ટિંગ કરો (દા.ત., ReactDOM.createRoot સાથે act નો ઉપયોગ કરીને).

એક લાઇવ ડેમો હૂકને એક્શનમાં બતાવે છે, જે React ની બહાર સ્ટોર કરેલા સાદા કાઉન્ટરને સિંક કરે છે અને વિઝ્યુઅલ ગ્લિચિસ વગર મલ્ટિપલ કમ્પોનન્ટ્સને અપડેટ કરે છે. ડેમો https://usesyncexternalstore.vercel.app/ પર ઉપલબ્ધ છે. સોર્સ કોડ GitHub પર છે, અને એક લાંબો લેખ અમલીકરણની વિગતો સમજાવે છે.

મુખ્ય વાત (Takeaway): એવી દુનિયામાં જ્યાં React UI ના ભાગોને ક્રમ બહાર (out of order) રેન્ડર કરી શકે છે, ત્યાં useSyncExternalStore એ એક્સટર્નલ ડેટા અને કમ્પોનન્ટ રેન્ડરિંગ વચ્ચેનો વિશ્વસનીય સેતુ છે. તે વિઝ્યુઅલ સુસંગતતા જાળવી રાખે છે, ગ્લોબલ સ્ટોર્સ સુધી સ્કેલ કરી શકે છે, અને લોકપ્રિય સ્ટેટ-મેનેજમેન્ટ લાઇબ્રેરીઓમાં પહેલેથી જ સામેલ છે. જ્યાં પણ તમારે નોન-React સ્ટેટ વાંચવાની જરૂર હોય ત્યાં તેનો ઉપયોગ કરો, અને તેના સંપૂર્ણ લાભો મેળવવા માટે સ્નેપશોટ્સને નાના અને સ્ટેબલ રાખો.