દરેક React ડેવલપર આખરે એક જ સમસ્યાનો સામનો કરે છે. તમે તમારા ટોપ-લેવલ App કમ્પોનન્ટની અંદર એક user object ફેચ કરો છો. પછી તમે તેને નીચે પાસ કરો છો. અને ફરી નીચે. એક route wrapper દ્વારા, એક layout shell દ્વારા, એક sidebar container દ્વારા, માત્ર એટલા માટે કે ત્રણ લેયર ઊંડે રહેલા એક નાના avatar કમ્પોનન્ટમાં પ્રોફાઇલ પિક્ચર ડિસ્પ્લે થઈ શકે. વચ્ચેના કમ્પોનન્ટ્સને તે user object સાથે કોઈ લેવાદેવા નથી. તેઓ ફક્ત પેકેજ આગળ પહોંચાડવાનું કામ કરી રહ્યા છે. આને 'prop drilling' કહેવામાં આવે છે, અને તે એક સ્વચ્છ component tree ને માહિતી ખોટી રીતે પહોંચાડવાની રમત (game of telephone) માં ફેરવી નાખે છે.

સાચી તકલીફ ત્યારે શરૂ થાય છે જ્યારે તે ડેટાનું માળખું બદલાય છે. કદાચ બેકએન્ડ user.avatar ને બદલે user.profile.avatar ને નેસ્ટેડ (nesting) કરવાનું શરૂ કરે. અચાનક તમારે પાંચ અલગ-અલગ ફાઇલોમાં TypeScript interfaces અથવા PropTypes એડિટ કરવા પડે છે જે પોતે ક્યારેય તે ડેટાનો ઉપયોગ કરતી નથી. અહીં જ React Context API કામ આવે છે.

Context કેવી રીતે ડેટા ફ્લોને ફરીથી ગોઠવે છે

Context ને તમારા ઘરના કેન્દ્રમાં રહેલા WiFi રાઉટર તરીકે વિચારો. તેના વગર, તમારા લેપટોપ સુધી સિગ્નલ પહોંચાડવા માટે તમારે દરેક રૂમમાંથી ઇથરનેટ કેબલ્સ પસાર કરવા પડે. તેની સાથે, રાઉટર હવામાં બ્રોડકાસ્ટ કરે છે, અને યોગ્ય પાસવર્ડ ધરાવતું કોઈપણ ઉપકરણ સીધું જ કનેક્ટ થઈ શકે છે. દીવાલો કોઈ અવરોધ બનતી નથી.

React ના સંદર્ભમાં, તમારા એપનું રૂટ (root) દરેક લેયરને કુરિયર તરીકે કામ કરવા કહે્યા વગર, component tree દ્વારા ડેટા બ્રોડકાસ્ટ કરી શકે છે. કોઈપણ નેસ્ટેડ કમ્પોનન્ટ તે બ્રોડકાસ્ટને સબ્સ્ક્રાઇબ કરી શકે છે અને તેને જે જોઈએ છે તે બરાબર મેળવી શકે છે.

ત્રણ મુખ્ય ભાગો

Context API ત્રણ મુખ્ય ભાગોમાં વહેંચાયેલું છે.

React.createContext() બ્રોડકાસ્ટ ચેનલ સેટઅપ કરે છે. તે એક ઓબ્જેક્ટ રિટર્ન કરે છે જેમાં Provider અને (જૂના કોડમાં) Consumer હોય છે. તમારે આપેલ ફીચર માટે આ માત્ર એક જ વાર કોલ કરવાની જરૂર છે.

The Provider એ એક કમ્પોનન્ટ છે જે તમારા ટ્રીના એક વિભાગને રેપ (wrap) કરે છે. તે value નામનો એક prop સ્વીકારે છે. તમે તે prop માં જે કંઈ પણ મૂકો છો તે દરેક વંશજ (descendant) માટે ઉપલબ્ધ થઈ જાય છે, ભલે તેઓ ગમે તેટલા ઊંડા હોય.

useContext એ એવું Hook છે જે ફંક્શન કમ્પોનન્ટને તે બ્રોડકાસ્ટ સાથે જોડવાની મંજૂરી આપે છે. તમારા કમ્પોનન્ટની અંદર, તમે બનાવેલા context ઓબ્જેક્ટને useContext માં પાસ કરો છો, અને તે વર્તમાન વેલ્યુ રિટર્ન કરે છે. બસ આટલું જ. કોઈ વધારાના રેપર્સ કે પ્રોપ્સની જરૂર નથી.

Hooks આવ્યા તે પહેલાં, તમારે render props સાથે Consumer પેટર્નનો ઉપયોગ કરવો પડતો હતો. તે કામ કરતું હતું, પરંતુ તેનાથી ઘણું બધું ઇન્ડેન્ટેશન (indentation) અને રેપર ક્લટર (wrapper clutter) ઊભું થતું હતું. useContext એ આ બધું તમારા ફંક્શન બોડીની અંદર એક સિંગલ લાઇન બનાવી દીધું.

Context નો ઉપયોગ ક્યારે ખરેખર યોગ્ય છે

માત્ર ટેવના કારણે Context નો ઉપયોગ ન કરો. તે એવા ડેટા માટે બનાવવામાં આવ્યું છે જે તમારા ટ્રીની વિવિધ શાખાઓમાં ઘણા અસંબંધિત કમ્પોનન્ટ્સ દ્વારા શેર કરવામાં આવે છે. સારા ઉદાહરણોમાં સામેલ છે:

  • Theme settings. માત્ર લાઈટ કે ડાર્ક મોડ જ નહીં, પણ spacing tokens, color palettes, અને font scales. આ બધું દરેક styled બટન અને મોડલ દ્વારા મેન્યુઅલી પસાર કરવું ઝડપથી કંટાળાજનક બની જાય છે.
  • User authentication. Login status, permissions array, અથવા વર્તમાન user object. તમારું હેડર બાર, ડેશબોર્ડ વિજેટ, અને પ્રાઇવેટ રૂટ ગાર્ડ ત્રણેય ટ્રીના અલગ-અલગ ખૂણામાં હોઈ શકે છે.
  • Language preferences. Locale strings, date formats, અને currency symbols. ફોર્મ લેબલ્સ જેવા ઊંડા કમ્પોનન્ટ્સને આની જરૂર હોય છે, પરંતુ રસ્તામાં આવતા દરેક પેરેન્ટ કમ્પોનન્ટને આ વિશે જાણવાની જરૂર નથી.
  • Shopping cart data. આઇટમ કાઉન્ટ, ટોટલ વેલ્યુ, અને add-to-cart ફંક્શન્સ. હેડર બેજ અને ચેકઆઉટ પેજ બંનેને સમાન સ્ટેટની જરૂર હોય છે, પરંતુ તેઓ સામાન્ય રીતે સંપૂર્ણપણે અલગ લેઆઉટ શાખાઓ હેઠળ હોય છે.

એક પ્રેક્ટિકલ થીમ સ્વિચર

Context ને એક્શનમાં જોવાનો સૌથી સ્પષ્ટ રસ્તો થીમ ટોગલ (theme toggle) છે. અહીં તમે તેને કેવી રીતે સેટ કરી શકો છો તે વિગતવાર સમજાવેલ છે.

પહેલા, એક ThemeContext.js ફાઇલ બનાવો. React.createContext() કોલ કરો અને તેનું પરિણામ સ્ટોર કરો. પછી એક ThemeProvider કમ્પોનન્ટ બનાવો જે useState અથવા useReducer સાથે વર્તમાન થીમનું સંચાલન કરે છે. તમારા કમ્પોનન્ટના બાળકોને (children) તમારા context ના Provider માં રેપ કરો, અને એક એવો ઓબ્જેક્ટ પાસ કરો જેમાં વર્તમાન થીમ અને તેને ટોગલ કરવા માટેનું ફંક્શન બંને હોય. ThemeProvider અને context ઓબ્જેક્ટ બંનેને એક્સપોર્ટ કરો.

બીજું, તમારી એપના એન્ટ્રી પોઈન્ટ પર જાઓ. ThemeProvider ને ઇમ્પોર્ટ કરો અને તમારી આખી એપ્લિકેશનને તેની સાથે રેપ કરો. જો તમે આ સ્ટેપ છોડી દેશો, તો પછીથી context વાંચવાનો પ્રયાસ કરતું કોઈપણ એન્ટિટી ફક્ત ડિફોલ્ટ વેલ્યુ જ જોઈ શકશે.

ત્રીજું, Header અથવા Content કમ્પોનન્ટની અંદર, context ઓબ્જેક્ટ અને useContext ને ઇમ્પોર્ટ કરો. Hook ને કોલ કરો, થીમ અને ટોગલ ફંક્શનને destructure કરો, અને તમારી CSS ક્લાસ કન્ડિશનલી એપ્લાય કરો. એક બટન ઉમેરો જે ટોગલને કોલ કરે. કમ્પોનન્ટ તેના પેરેન્ટ પાસેથી ક્યારેય theme prop મેળવતો નથી. તે સીધો સિગ્નલ હવામાંથી ખેંચી લે છે.

Prop Drilling, Context, કે Redux?

આ સાધનો વચ્ચે પસંદગી કરવી એ વફાદારી વિશે ઓછું અને તમારા સ્ટેટ (state) ના સ્વરૂપ વિશે વધુ છે.

Prop drilling બે અથવા ત્રણ લેવલની ઊંડાઈ માટે એકદમ યોગ્ય છે. તે સ્પષ્ટ છે, તમારા IDE માં ટ્રેસ કરવામાં સરળ છે, અને ડિપેન્ડન્સીઝ (dependencies) ને સ્પષ્ટ રાખે છે. સમસ્યાઓ ત્યારે જ દેખાય છે જ્યારે તમે એક જ પ્રોપને છ કે સાત લેયર સુધી પસાર કરવાનું શરૂ કરો છો.

Context API React ની સાથે જ આવે છે. તેનો અર્થ એ છે કે કોઈ વધારાનું બંડલ સાઈઝ (bundle size) નથી અને કોઈ બાહ્ય સેટઅપની જરૂર નથી. તે નાનાથી મધ્યમ કદના ગ્લોબલ સ્ટેટને સુંદર રીતે હેન્ડલ કરે છે, ખાસ કરીને એવા ડેટાને જે વારંવાર બદલાતા નથી જેમ કે થીમ્સ અથવા યુઝર પ્રોફાઇલ્સ.

Redux માટે વધારાની લાઇબ્રેરીઓ ઇન્સ્ટોલ કરવી અને બૉઇલરપ્લેટ (boilerplate) લખવી જરૂરી છે. જ્યારે તમારું સ્ટેટ લોજિક જટિલ હોય, જ્યારે સ્ટેટના અનેક સ્લાઇસ (slices) ઊંડાણપૂર્વક એકબીજા સાથે જોડાયેલા હોય, અથવા જ્યારે તમને time-travel debugging અને middleware ની જરૂર હોય ત્યારે તે ફાયદાકારક રહે છે. સાદા ગ્લોબલ ડેટા માટે, Redux જરૂરિયાત કરતા વધારે (overkill) છે.

પરફોર્મન્સની વાસ્તવિકતા જેના વિશે કોઈ વાત નથી કરતું

અહીં એક એવી બાબત છે જે જુનિયર અને સિનિયર અમલીકરણો (implementations) વચ્ચેનો તફાવત સ્પષ્ટ કરે છે. જ્યારે Context Provider ની વેલ્યુ બદલાય છે, ત્યારે તે કોન્ટેક્સ્ટનો ઉપયોગ કરતું દરેક કમ્પોનન્ટ ફરીથી રેન્ડર (re-render) થાય છે. તે મહત્વનું નથી કે જે ચોક્કસ સ્લાઇસ સાથે તે કમ્પોનન્ટને લેવાદેવા છે તે બદલાયો છે કે નહીં. React નવી રેફરન્સ જુએ છે અને અપડેટ શેડ્યૂલ કરે છે.

જો તમે તમારા આખા એપ્લિકેશન સ્ટેટને એક વિશાળ StoreContext માં નાખી દો છો, તો તમે અસરકારક રીતે તમારા આખા UI ને એકબીજા સાથે ચોંટાડી દીધું છે. થીમ સેટિંગ બદલવાથી તમારું શોપિંગ કાર્ટ, તમારા ડેશબોર્ડ ચાર્ટ્સ અને તમારી નોટિફિકેશન લિસ્ટ ફરીથી રેન્ડર થશે. તે બિનજરૂરી કામ છે.

તમારા કોન્ટેક્સ્ટને ડોમેન (domain) મુજબ વિભાજિત કરો. વિઝ્યુઅલ સેટિંગ્સ માટે ThemeContext, પ્રોફાઇલ ડેટા માટે UserContext, અને કોમર્સ સ્ટેટ માટે CartContext રાખો. જો યુઝર તેમનું ડિસ્પ્લે નામ એડિટ કરે છે, તો પ્રોડક્ટ ગ્રીડને અડક્યા વગર તમારું હેડર અપડેટ થઈ જશે. સાથે જ, તમે Provider ના value પ્રોપમાં શું પાસ કરો છો તેના બાબતે સાવધ રહો. જો તમે રેન્ડરિંગ દરમિયાન ઇનલાઇન { theme, toggleTheme } જેવું ઓબ્જેક્ટ લિટરલ પાસ કરો છો, તો તમે દરેક રેન્ડર પર એક નવી રેફરન્સ બનાવો છો અને બિનજરૂરી અપડેટ્સ ટ્રિગર કરો છો. જો વેલ્યુમાં ફંક્શન્સ અથવા નોન-પ્રિમીટિવ ડેટા હોય, તો useMemo સાથે તેને સ્ટેબિલાઇઝ કરો.

ભૂલો જે કલાકો બગાડે છે

બે એવી ભૂલો છે જે ટીમોને વારંવાર પકડી પાડે છે.

કોન્ટેક્સ્ટ ઓબ્જેક્ટ એક્સપોર્ટ કરવાનું ભૂલી જવું. ThemeProvider કમ્પોનન્ટને એક્સપોર્ટ કરવો અને પછી useContext(ThemeProvider) ને કોલ કરવાનો પ્રયાસ કરવો સરળ છે. તે કામ કરવાની રીત નથી. Hook ને createContext દ્વારા રિટર્ન થયેલ કોન્ટેક્સ્ટ ઓબ્જેક્ટની જરૂર હોય છે, વ્રેપર કમ્પોનન્ટની નહીં. જો તમે ફક્ત Provider ને જ એક્સપોર્ટ કરો છો, તો તમારા કન્ઝ્યુમર્સ પાસે ઇમ્પોર્ટ કરવા માટે કંઈ જ રહેશે નહીં.

તેના Provider ની બહાર useContext ને કોલ કરવું. Hook એ ડિફોલ્ટ વેલ્યુ રિટર્ન કરે છે જે તમે createContext માં પાસ કરી હતી. જો તમે ડિફોલ્ટ વેલ્યુ પાસ નથી કરી, તો તમને undefined મળશે. જો તમારું કમ્પોનન્ટ ટ્રી Provider કરતા DOM માં ઉપર કન્ઝ્યુમરને રેન્ડર કરે છે, અથવા જો Provider સંપૂર્ણપણે ગેરહાજર છે, તો તમારો ડેટા બિલકુલ નહીં મળે. ખાતરી કરો કે તમારી index અથવા root ફાઇલ ખરેખર એપને વ્રેપ (wrap) કરે છે.

સાચો નિષ્કર્ષ

React Context એ સ્ટેટ મેનેજમેન્ટ ક્રાંતિ નથી. તે એક ચોક્કસ સ્પેસિયલ સમસ્યા માટેનું લક્ષિત સાધન છે: દરેક લેયરને પોસ્ટ ઓફિસ બનાવ્યા વગર ડેટાને દૂરના કમ્પોનન્ટ્સ સુધી પહોંચાડવો. તેનો ઉપયોગ ખરેખર ગ્લોબલ ડેટા માટે કરો, રેન્ડરિંગ પરફોર્મન્સ જાળવી રાખવા માટે તમારા કોન્ટેક્સ્ટને ડોમેન મુજબ વિભાજિત રાખો, અને સિગ્નલ વાંચવાનો પ્રયાસ કરતા પહેલા હંમેશા તમારા ટ્રીને યોગ્ય Provider સાથે વ્રેપ કરો. આ આદતો કેળવો, અને તમારા કમ્પોનન્ટ ટ્રી ક્લીન, ફાસ્ટ અને સમજવામાં સરળ રહેશે.