എല്ലാ React ഡെവലപ്പർമാരും ഒടുവിൽ ഒരേ പ്രതിസന്ധി നേരിടാറുണ്ട്. നിങ്ങളുടെ ഏറ്റവും മുകളിലുള്ള (top-level) App കംപോണന്റിനുള്ളിൽ നിങ്ങൾ ഒരു user ഒബ്ജക്റ്റ് ഫെച്ച് ചെയ്യുന്നു. എന്നിട്ട് അത് താഴേക്ക് പാസ് ചെയ്യുന്നു. വീണ്ടും വീണ്ടും താഴേക്ക്. ഒരു റൂട്ട് റാപ്പർ (route wrapper), ഒരു ലേഔട്ട് ഷെൽ (layout shell), ഒരു സൈഡ്ബാർ കണ്ടെയ്നർ എന്നിവയിലൂടെ ഇത് കടന്നുപോകുന്നു; മൂന്ന് ലെയറുകൾ താഴെയുള്ള ഒരു ചെറിയ അവതാർ കംപോണന്റിന് ഒരു പ്രൊഫൈൽ ചിത്രം കാണിക്കാൻ വേണ്ടി മാത്രം. ഇടയിലുള്ള കംപോണന്റുകൾക്ക് ആ user ഒബ്ജക്റ്റുമായി യാതൊരു ബന്ധവുമില്ല. അവ വെറും ഒരു പാഴ്സൽ കൈമാറുന്നതുപോലെയാണ് പ്രവർത്തിക്കുന്നത്. ഇതാണ് 'prop drilling'. ഇത് ഒരു വൃത്തിയുള്ള കംപോണന്റ് ട്രീയെ ആശയക്കുഴപ്പമുണ്ടാക്കുന്ന ഒരു 'game of telephone' ആയി മാറ്റുന്നു.
ഡാറ്റയുടെ ഘടന (shape) മാറുമ്പോഴാണ് യഥാർത്ഥ ബുദ്ധിമുട്ട് തുടങ്ങുന്നത്. ഒരുപക്ഷേ ബാക്കെൻഡ് user.avatar-ന് പകരം user.profile.avatar എന്ന് നൽകിയേക്കാം. പെട്ടെന്ന്, ആ ഡാറ്റ ഉപയോഗിക്കാത്ത അഞ്ച് ഫയലുകളിലെ TypeScript ഇന്റർഫേസുകളോ PropTypes-ഓ നിങ്ങൾ എഡിറ്റ് ചെയ്യേണ്ടി വരുന്നു. ഇവിടെയാണ് React Context API സഹായത്തിനെത്തുന്നത്.
എങ്ങനെ Context ഡാറ്റാ ഫ്ലോയെ മാറ്റുന്നു
Context-നെ നിങ്ങളുടെ വീടിന്റെ മധ്യഭാഗത്തുള്ള ഒരു WiFi റൂട്ടറായി സങ്കൽപ്പിക്കുക. ഇതില്ലെങ്കിൽ, ലാപ്ടോപ്പിലേക്ക് സിഗ്നൽ ലഭിക്കാൻ ഓരോ മുറിയിലൂടെയും ഇഥർനെറ്റ് കേബിളുകൾ വലിച്ചുനീട്ടേണ്ടി വരും. എന്നാൽ റൂട്ടർ ഉണ്ടെങ്കിൽ, അത് വായുവിലൂടെ സിഗ്നൽ ബ്രോഡ്കാസ്റ്റ് ചെയ്യുന്നു, ശരിയായ പാസ്വേഡുള്ള ഏത് ഉപകരണത്തിനും നേരിട്ട് കണക്ട് ചെയ്യാം. ഭിത്തികൾ ഒരു തടസ്സമല്ല.
React-ന്റെ ഭാഷയിൽ പറഞ്ഞാൽ, ഓരോ ലെയറിനെയും ഒരു കൊറിയർ പോലെ പ്രവർത്തിക്കാൻ ആവശ്യപ്പെടാതെ തന്നെ, നിങ്ങളുടെ ആപ്പിന്റെ റൂട്ടിന് (root) കംപോണന്റ് ട്രീയിലൂടെ ഡാറ്റ ബ്രോഡ്കാസ്റ്റ് ചെയ്യാൻ കഴിയും. ഏത് നെസ്റ്റഡ് കംപോണന്റിനും ആ ബ്രോഡ്കാസ്റ്റിൽ സബ്സ്ക്രൈബ് ചെയ്യാനും തനിക്ക് ആവശ്യമുള്ളത് കൃത്യമായി സ്വീകരിക്കാനും കഴിയും.
മൂന്ന് പ്രധാന ഭാഗങ്ങൾ
Context API പ്രധാനമായും മൂന്ന് ഭാഗങ്ങളായാണ് പ്രവർത്തിക്കുന്നത്.
React.createContext() ബ്രോഡ്കാസ്റ്റ് ചാനൽ സജ്ജീകരിക്കുന്നു. ഇത് ഒരു Provider-ഉം (പഴയ കോഡുകളിൽ) ഒരു Consumer-ഉം അടങ്ങിയ ഒരു ഒബ്ജക്റ്റ് തിരികെ നൽകുന്നു. ഒരു ഫീച്ചറിനായി ഇത് ഒരു തവണ മാത്രം വിളിച്ചാൽ മതിയാകും.
The Provider എന്നത് നിങ്ങളുടെ ട്രീയുടെ ഒരു ഭാഗത്തെ പൊതിഞ്ഞുനിൽക്കുന്ന (wrap ചെയ്യുന്ന) ഒരു കംപോണന്റാണ്. ഇതിന് value എന്നൊരു പ്രോപ്പ് (prop) ഉണ്ട്. ആ പ്രോപ്പിൽ നിങ്ങൾ എന്ത് നൽകിയാലും, എത്ര ആഴത്തിലുള്ളതാണെങ്കിലും അത് എല്ലാ ഡെസ്കണ്ടന്റ് (descendant) കംപോണന്റുകൾക്കും ലഭ്യമാകും.
useContext എന്നത് ഒരു ഫങ്ക്ഷൻ കംപോണന്റിന് ആ ബ്രോഡ്കാസ്റ്റിൽ നിന്ന് വിവരങ്ങൾ എടുക്കാൻ സഹായിക്കുന്ന ഒരു Hook ആണ്. നിങ്ങളുടെ കംപോണന്റിനുള്ളിൽ, നിങ്ങൾ നിർമ്മിച്ച context ഒബ്ജക്റ്റ് useContext-ലേക്ക് പാസ് ചെയ്താൽ, അത് നിലവിലെ വാല്യൂ തിരികെ നൽകും. അത്രമാത്രം! അധികമായ റാപ്പറുകളോ പ്രോപ്പുകളോ ആവശ്യമില്ല.
Hooks വരുന്നതിന് മുമ്പ്, render props ഉപയോഗിച്ച് Consumer പാറ്റേൺ ഉപയോഗിക്കേണ്ടി വരുമായിരുന്നു. അത് പ്രവർത്തിക്കുമായിരുന്നുവെങ്കിലും, കോഡിൽ അനാവശ്യമായ ഇൻഡന്റേഷനും (indentation) റാപ്പറുകളും ഉണ്ടാക്കിയിരുന്നു. useContext ഇതെല്ലാം നിങ്ങളുടെ ഫങ്ക്ഷൻ ബോഡിനുള്ളിൽ ഒരു വരിയായി ലളിതമാക്കി.
എപ്പോഴാണ് Context ഉപയോഗിക്കുന്നത് അർത്ഥവത്താവുന്നത്
ശീലത്തിന്റെ ഭാഗമായി Context ഉപയോഗിക്കരുത്. നിങ്ങളുടെ ട്രീയുടെ വിവിധ ശാഖകളിലായി (branches) പരസ്പരം ബന്ധമില്ലാത്ത നിരവധി കംപോണന്റുകൾ പങ്കിടുന്ന ഡാറ്റയ്ക്കാണ് ഇത് നിർമ്മിച്ചിരിക്കുന്നത്. താഴെ പറയുന്നവയ്ക്ക് ഇത് അനുയോജ്യമാണ്:
- Theme settings. വെറും ലൈറ്റ് അല്ലെങ്കിൽ ഡാർക്ക് മോഡ് മാത്രമല്ല, സ്പേസിംഗ് ടോക്കണുകൾ, കളർ പാലറ്റുകൾ, ഫോണ്ട് സ്കെയിലുകൾ എന്നിവയും ഇതിൽ ഉൾപ്പെടുന്നു. ഇവ ഓരോ സ്റ്റൈൽഡ് ബട്ടണിലൂടെയും മോഡലിലൂടെയും കൈമാറുന്നത് ബുദ്ധിമുട്ടാണ്.
- User authentication. ലോഗിൻ സ്റ്റാറ്റസ്, പെർമിഷൻ അറേ, അല്ലെങ്കിൽ നിലവിലെ യൂസർ ഒബ്ജക്റ്റ് എന്നിവ. നിങ്ങളുടെ ഹെഡർ ബാർ, ഡാഷ്ബോർഡ് വിഡ്ജറ്റ്, പ്രൈവറ്റ് റൂട്ട് ഗാർഡ് എന്നിവ ട്രീയുടെ വിവിധ ഭാഗങ്ങളിലായിരിക്കാം.
- Language preferences. ലോക്കൽ സ്ട്രിംഗുകൾ, ഡേറ്റ് ഫോർമാറ്റുകൾ, കറൻസി ചിഹ്നങ്ങൾ എന്നിവ. ഫോം ലേബലുകൾ പോലുള്ള ഡീപ് കംപോണന്റുകൾക്ക് ഇവ ആവശ്യമാണ്, എന്നാൽ അവയുടെ എല്ലാ പാരന്റുകളും ഇതിനെക്കുറിച്ച് അറിയേണ്ടതില്ല.
- Shopping cart data. ഐറ്റം കൗണ്ട്, ടോട്ടൽ വാല്യൂ, ആഡ്-ടു-കാർട്ട് ഫങ്ക്ഷനുകൾ എന്നിവ. ഹെഡർ ബാഡ്ജും ചെക്ക്ഔട്ട് പേജും ഒരേ സ്റ്റേറ്റ് ആവശ്യപ്പെടുന്നുണ്ടെങ്കിലും അവ സാധാരണയായി വ്യത്യസ്ത ലേഔട്ട് ബ്രാഞ്ചുകളിലാണ് ഇരിക്കുന്നത്.
ഒരു പ്രായോഗികമായ Theme Switcher
Context പ്രവർത്തിക്കുന്നത് കാണാനുള്ള ഏറ്റവും വ്യക്തമായ വഴികളിലൊന്ന് ഒരു theme toggle ആണ്. പ്രധാനപ്പെട്ട കാര്യങ്ങൾ ഒഴിവാക്കാതെ ഇത് എങ്ങനെ ചെയ്യാം എന്ന് നോക്കാം.
ഒന്നാമതായി, ഒരു ThemeContext.js ഫയൽ നിർമ്മിക്കുക. React.createContext() വിളിക്കുകയും അതിന്റെ റിസൾട്ട് സ്റ്റോർ ചെയ്യുകയും ചെയ്യുക. തുടർന്ന് useState അല്ലെങ്കിൽ useReducer ഉപയോഗിച്ച് നിലവിലെ തീം നിയന്ത്രിക്കുന്ന ഒരു ThemeProvider കംപോണന്റ് നിർമ്മിക്കുക. നിലവിലെ തീമും അത് മാറ്റാനുള്ള ഫങ്ക്ഷനും അടങ്ങിയ ഒരു ഒബ്ജക്റ്റ് പാസ് ചെയ്തുകൊണ്ട്, നിങ്ങളുടെ കംപോണന്റുകളെ (children) context-ന്റെ Provider കൊണ്ട് റാപ്പ് ചെയ്യുക. ThemeProvider-ഉം context ഒബ്ജക്റ്റും എക്സ്പോർട്ട് ചെയ്യുക.
രണ്ടാമതായി, നിങ്ങളുടെ ആപ്പിന്റെ എൻട്രി പോയിന്റിലേക്ക് (entry point) പോകുക. ThemeProvider ഇംപോർട്ട് ചെയ്യുകയും നിങ്ങളുടെ മുഴുവൻ ആപ്പിനെയും അത് ഉപയോഗിച്ച് റാപ്പ് ചെയ്യുകയും ചെയ്യുക. ഈ ഘട്ടം ഒഴിവാക്കിയാൽ, പിന്നീട് context വായിക്കാൻ ശ്രമിക്കുന്നവയ്ക്ക് ഡിഫോൾട്ട് വാല്യൂ മാത്രമേ ലഭിക്കൂ.
മൂന്നാമതായി, ഒരു Header അല്ലെങ്കിൽ Content കംപോണന്റിനുള്ളിൽ, context ഒബ്ജക്റ്റും useContext-ഉം ഇംപോർട്ട് ചെയ്യുക. Hook വിളിക്കുക, തീമും ടോഗിൾ ഫങ്ക്ഷനും ഡിസ്ട്രക്ചർ (destructure) ചെയ്യുക, തുടർന്ന് നിങ്ങളുടെ CSS ക്ലാസുകൾ കണ്ടിഷണലായി പ്രയോഗിക്കുക. ടോഗിൾ വിളിക്കുന്ന ഒരു ബട്ടൺ ചേർക്കുക. ഈ കംപോണന്റ് അതിന്റെ പാരന്റിൽ നിന്ന് ഒരു theme പ്രോപ്പും സ്വീകരിക്കുന്നില്ല. അത് നേരിട്ട് സിഗ്നൽ സ്വീകരിക്കുന്നു.
Prop Drilling, Context, or Redux?
ഈ ടൂളുകൾക്കിടയിൽ തിരഞ്ഞെടുക്കുന്നത് ഒരു പ്രത്യേക ടൂളിനോടുള്ള വിശ്വസ്തതയല്ല, മറിച്ച് നിങ്ങളുടെ സ്റ്റേറ്റിന്റെ (state) സ്വഭാവമാണ്.
രണ്ട് അല്ലെങ്കിൽ മൂന്ന് ലെവലുകൾ വരെ ആഴമുള്ള ഘടനകളിൽ Prop drilling തികച്ചും അനുയോജ്യമാണ്. ഇത് വ്യക്തമാണ്, നിങ്ങളുടെ IDE-യിൽ എളുപ്പത്തിൽ കണ്ടെത്താം, കൂടാതെ ഡിപെൻഡൻസികൾ (dependencies) വ്യക്തമായി നിലനിർത്തുകയും ചെയ്യുന്നു. എന്നാൽ ഒരേ പ്രോപ്പ് (prop) ആറ് അല്ലെങ്കിൽ ഏഴ് ലെയറുകളിലൂടെ കടത്തിവിടാൻ തുടങ്ങുമ്പോഴാണ് പ്രശ്നങ്ങൾ ഉണ്ടാകുന്നത്.
Context API React-നോടൊപ്പം തന്നെ ലഭിക്കുന്നു. അതായത്, അധികമായ ബണ്ടിൽ സൈസ് (bundle size) ആവശ്യമില്ല, പുറമെ നിന്ന് ഒന്നും സെറ്റപ്പ് ചെയ്യേണ്ടതില്ല. ചെറിയതോ ഇടത്തരമോ ആയ ഗ്ലോബൽ സ്റ്റേറ്റുകൾ കൈകാര്യം ചെയ്യാൻ ഇത് മികച്ചതാണ്, പ്രത്യേകിച്ച് തീമുകൾ (themes) അല്ലെങ്കിൽ യൂസർ പ്രൊഫൈലുകൾ (user profiles) പോലുള്ള ഇടയ്ക്കിടെ മാറാത്ത ഡാറ്റകൾക്ക് ഇത് വളരെ അനുയോജ്യമാണ്.
Redux ഉപയോഗിക്കാൻ അധിക ലൈബ്രറികൾ ഇൻസ്റ്റാൾ ചെയ്യേണ്ടതും ബോയിലർപ്ലേറ്റ് (boilerplate) കോഡ് എഴുതേണ്ടതുമാണ്. നിങ്ങളുടെ സ്റ്റേറ്റ് ലോജിക് സങ്കീർണ്ണമാകുമ്പോഴോ, സ്റ്റേറ്റിന്റെ വിവിധ ഭാഗങ്ങൾ (slices) പരസ്പരം ആഴത്തിൽ ബന്ധപ്പെട്ടിരിക്കുമ്പോഴോ, അല്ലെങ്കിൽ ടൈം-ട്രാവൽ ഡിബഗ്ഗിംഗും (time-travel debugging) മിഡിൽവെയറും (middleware) ആവശ്യമായി വരുമ്പോഴോ ആണ് ഇത് ഗുണകരമാകുന്നത്. ലളിതമായ ഗ്ലോബൽ ഡാറ്റയ്ക്ക് Redux അനാവശ്യമായിപ്പോകും (overkill).
ആരും സംസാരിക്കാത്ത പെർഫോമൻസ് യാഥാർത്ഥ്യം
ജൂനിയർ ലെവലിലുള്ളവരും സീനിയർ ലെവലിലുള്ളവരും തമ്മിലുള്ള വ്യത്യാസം തിരിച്ചറിയാൻ സഹായിക്കുന്ന ഒരു കാര്യമാണിത്. ഒരു Context Provider-ന്റെ വാല്യൂ (value) മാറുമ്പോൾ, ആ കോൺടെക്സ്റ്റ് ഉപയോഗിക്കുന്ന എല്ലാ കംപോണന്റുകളും വീണ്ടും റെൻഡർ (re-render) ചെയ്യപ്പെടുന്നു. ആ കംപോണന്റിന് ആവശ്യമുള്ള പ്രത്യേക ഭാഗം (slice) മാറിയിട്ടില്ലെങ്കിൽ പോലും ഇത് സംഭവിക്കും. പുതിയ റെഫറൻസ് (reference) കാണുന്നതോടെ React ഒരു അപ്ഡേറ്റ് ഷെഡ്യൂൾ ചെയ്യുന്നു.
നിങ്ങളുടെ ആപ്ലിക്കേഷന്റെ മുഴുവൻ സ്റ്റേറ്റും ഒരു വലിയ StoreContext-ലേക്ക് മാറ്റിവെച്ചാൽ, നിങ്ങൾ യഥാർത്ഥത്തിൽ നിങ്ങളുടെ മുഴുവൻ UI-യെയും ഒന്നിച്ച് ഒട്ടിച്ചു വെച്ചിരിക്കുകയാണ്. ഒരു തീം സെറ്റിംഗ് മാറ്റുന്നത് നിങ്ങളുടെ ഷോപ്പിംഗ് കാർട്ട്, ഡാഷ്ബോർഡ് ചാർട്ടുകൾ, നോട്ടിഫിക്കേഷൻ ലിസ്റ്റ് എന്നിവയെല്ലാം വീണ്ടും റെൻഡർ ചെയ്യിക്കും. അത് അനാവശ്യമായ ജോലിയാണ്.
നിങ്ങളുടെ കോൺടെക്സ്റ്റുകളെ ഡൊമൈൻ (domain) അനുസരിച്ച് തിരിക്കുക. വിഷ്വൽ സെറ്റിംഗുകൾക്കായി ഒരു ThemeContext, പ്രൊഫൈൽ ഡാറ്റയ്ക്കായി ഒരു UserContext, കൊമേഴ്സ് സ്റ്റേറ്റിനായി ഒരു CartContext എന്നിവ സൂക്ഷിക്കുക. ഒരു ഉപയോക്താവ് അവരുടെ ഡിസ്പ്ലേ പേര് മാറ്റിയാൽ, പ്രൊഡക്റ്റ് ഗ്രിഡിനെ ബാധിക്കാതെ തന്നെ നിങ്ങളുടെ ഹെഡർ അപ്ഡേറ്റ് ചെയ്യപ്പെടും. കൂടാതെ, പ്രൊവൈഡറിലെ (Provider) value പ്രോപ്പിലേക്ക് നിങ്ങൾ എന്ത് നൽകുന്നു എന്ന കാര്യത്തിലും ശ്രദ്ധ വേണം. റെൻഡറിംഗിനിടെ { theme, toggleTheme } എന്ന രീതിയിൽ ഒരു ഒബ്ജക്റ്റ് ലിറ്ററൽ (object literal) നേരിട്ട് നൽകിയാൽ, ഓരോ റെൻഡറിംഗിലും പുതിയൊരു റെഫറൻസ് സൃഷ്ടിക്കപ്പെടുകയും അനാവശ്യമായ അപ്ഡേറ്റുകൾ ഉണ്ടാവുകയും ചെയ്യും. വാല്യൂവിൽ ഫംഗ്ഷനുകളോ നോൺ-പ്രിമിറ്റീവ് (non-primitive) ഡാറ്റയോ ഉണ്ടെങ്കിൽ useMemo ഉപയോഗിച്ച് ആ ഘടന സ്ഥിരപ്പെടുത്തുക.
മണിക്കൂറുകൾ നഷ്ടപ്പെടുത്തുന്ന തെറ്റുകൾ
ടീമുകൾ വീണ്ടും വീണ്ടും വരുത്തുന്ന രണ്ട് തെറ്റുകൾ ഇവയാണ്.
കോൺടെക്സ്റ്റ് ഒബ്ജക്റ്റ് എക്സ്പോർട്ട് ചെയ്യാൻ മറന്നുപോകുന്നത്. ThemeProvider കംപോണന്റ് എക്സ്പോർട്ട് ചെയ്ത ശേഷം useContext(ThemeProvider) എന്ന് വിളിക്കാൻ ശ്രമിക്കുന്നത് സാധാരണമാണ്. എന്നാൽ അത് അങ്ങനെയാണ് പ്രവർത്തിക്കുന്നത്. ഈ ഹുക്കിന് (Hook) createContext-ൽ നിന്ന് ലഭിക്കുന്ന കോൺടെക്സ്റ്റ് ഒബ്ജക്റ്റ് ആണ് വേണ്ടത്, വ്രാപ്പർ കംപോണന്റ് (wrapper component) അല്ല. നിങ്ങൾ പ്രൊവൈഡർ (Provider) മാത്രം എക്സ്പോർട്ട് ചെയ്താൽ, അത് ഉപയോഗിക്കുന്നവർക്ക് ഇംപോർട്ട് ചെയ്യാൻ ഒന്നും ലഭിക്കില്ല.
പ്രൊവൈഡറിന് പുറത്ത് useContext വിളിക്കുന്നത്. createContext-ലേക്ക് നിങ്ങൾ നൽകിയ ഡിഫോൾട്ട് വാല്യൂ ആണ് ഈ ഹുക്ക് തിരികെ നൽകുന്നത്. നിങ്ങൾ ഒരു ഡിഫോൾട്ട് വാല്യൂ നൽകിയിട്ടില്ലെങ്കിൽ, നിങ്ങൾക്ക് undefined ലഭിക്കും. നിങ്ങളുടെ കംപോണന്റ് ട്രീ (component tree) പ്രൊവൈഡറിനേക്കാൾ മുകളിലായി കൺസ്യൂമറെ (consumer) റെൻഡർ ചെയ്യുന്നുണ്ടെങ്കിലോ, അല്ലെങ്കിൽ പ്രൊവൈഡർ പൂർണ്ണമായും ഇല്ലെങ്കിലോ, ഡാറ്റ ലഭിക്കില്ല. നിങ്ങളുടെ ഇൻഡക്സ് (index) അല്ലെങ്കിൽ റൂട്ട് (root) ഫയൽ ആപ്ലിക്കേഷനെ ശരിയായി റാപ്പ് (wrap) ചെയ്യുന്നുണ്ടെന്ന് ഉറപ്പുവരുത്തുക.
യഥാർത്ഥ പാഠം
React Context എന്നത് ഒരു സ്റ്റേറ്റ് മാനേജ്മെന്റ് വിപ്ലവമല്ല. മറിച്ച്, ഒരു പ്രത്യേക പ്രശ്നത്തിന് പരിഹാരമായി ഉപയോഗിക്കാവുന്ന ടൂൾ മാത്രമാണ്: ഓരോ ലെയറിനെയും ഒരു പോസ്റ്റ് ഓഫീസാക്കി മാറ്റാതെ തന്നെ, ദൂരെയുള്ള കംപോണന്റുകളിലേക്ക് ഡാറ്റ എത്തിക്കുക എന്നതാണ് ഇതിന്റെ ലക്ഷ്യം. യഥാർത്ഥത്തിൽ ഗ്ലോബൽ ആയ ഡാറ്റകൾക്കായി മാത്രം ഇത് ഉപയോഗിക്കുക, റെൻഡറിംഗ് പെർഫോമൻസ് നിലനിർത്താൻ കോൺടെക്സ്റ്റുകളെ ഡൊമൈൻ അനുസരിച്ച് തിരിക്കുക, കൂടാതെ ഡാറ്റ ലഭിക്കുന്നതിന് മുമ്പ് നിങ്ങളുടെ ട്രീ ശരിയായ പ്രൊവൈഡർ ഉപയോഗിച്ച് റാപ്പ് ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക. ഈ ശീലങ്ങൾ കൃത്യമായി പാലിച്ചാൽ നിങ്ങളുടെ കംപോണന്റ് ട്രീകൾ വൃത്തിയുള്ളതും വേഗതയുള്ളതും എളുപ്പത്തിൽ മനസ്സിലാക്കാവുന്നതുമായിരിക്കും.
