Kila mtengenezaji wa React hatimaye anakutana na kikwazo kilekile. Unapata object ya mtumiaji ndani ya component yako ya juu kabisa ya App. Kisha unaiwasilisha chini. Na chini tena. Kupitia route wrapper, kupitia layout shell, kupitia sidebar container, ili tu component ndogo ya avatar iliyo tabaka tatu ndani iweze kuonyesha picha ya wasifu. Component zilizo katikati hazihitaji object hiyo ya mtumiaji. Zinachofanya ni kusafirisha kifurushi tu. Hiyo ndiyo prop drilling, na inageuza mti safi wa component kuwa mchezo wa kuchosha wa kusambaza ujumuzi kwa mnyororo (game of telephone).

Maumivu ya kweli huanza pale muundo wa data hiyo unapobadilika. Labda backend inaanza kutumia user.profile.avatar badala ya user.avatar. Ghafla unajikuta unahariri TypeScript interfaces au PropTypes kwenye faili tano ambazo hazitumii data hiyo kabisa. Hapo ndipo React Context API inapoingia msaada.

Jinsi Context Inavyobadilisha Mtiririko wa Data

Fikiria Context kama router ya WiFi iliyopo katikati ya nyumba yako. Bila hiyo, ungehitaji nyaya za Ethernet zinazopita kila chumba ili kupata mawimbi kwenye laptop yako. Ukiwa nayo, router inatangaza mawimbi kupitia hewa, na kifaa chochote chenye nywila sahihi kinaweza kuunganishwa moja kwa moja. Kuta hazina umuhimu.

Katika lugha ya React, mzizi wa app yako unaweza kutangaza data kupitia mti wa component bila kuiomba kila tabaka ifanye kazi kama msafirishaji. Component yoyote iliyojificha ndani inaweza kujiunga na tangazo hilo na kupokea kile hasa kinachohitajika.

Vipengele Vitatu vya Msingi

Context API inajumuisha sehemu tatu zinazofanya kazi.

React.createContext() inaunda chaneli ya utangazaji. Inarudisha object yenye Provider na (katika kodi za zamani) Consumer. Unahitaji kuitumia mara moja tu kwa kipengele fulani.

The Provider ni component inayofunika sehemu ya mti wako (tree). Inapokea prop moja inayoitwa value. Chochote unachoweka kwenye prop hiyo kinapatikana kwa kila mfuatiliaji (descendant), bila kujali wako ndani kiasi gani.

useContext ni Hook inayoruhusu function component kupata tangazo hilo. Ndani ya component yako, unapitisha context object uliyounda kwenye useContext, na inakurudishia thamani ya sasa. Hivyo tu. Hakuna wrappers, hakuna props za ziada.

Kabla ya Hooks kuingia, ilibidi utumie mfumo wa Consumer ukitumia render props. Ilifanya kazi, lakini ilisababisha mchanganyiko mkubwa wa indentation na wrapper nyingi. useContext ilifanya kila kitu kuwa rahisi kwa mstari mmoja ndani ya mwili wa function yako.

Wakati Context Inapofaa Kweli

Usitumie Context kwa mazoea tu. Imeundwa kwa ajili ya data ambayo component nyingi zisizohusiana zinashiriki katika matawi tofauti ya mti wako. Mifano mizuri ni pamoja na:

  • Mipangilio ya Theme. Sio tu mode ya mwanga (light) au giza (dark), bali pia spacing tokens, rangi (color palettes), na ukubwa wa fonti. Kufunga hizi kwa mkono kupitia kila button na modal inachosha haraka.
  • Uthibitishaji wa mtumiaji (User authentication). Hali ya kuingia (login status), array ya ruhusa (permissions), au object ya mtumiaji wa sasa. Header bar yako, widget ya dashboard, na route guard ya faragha zinaweza kuwa katika pembe tofauti za mti.
  • Mapendeleo ya lugha. Locale strings, mifumo ya tarehe, na alama za sarafu. Component za ndani sana kama lebo za fomu zinahitaji hizi bila kila mzazi kwenye njia hiyo kuhitaji kuzijua.
  • Data ya kikapu cha manunuzi. Idadi ya bidhaa, thamani ya jumla, na kazi za kuongeza kwenye kikapu. Badge ya header na ukurasa wa malipo (checkout) yanahitaji hali (state) ile ile, lakini kwa kawaida yanapatikana chini ya matawi tofauti kabisa ya layout.

Mfano wa Kubadilisha Theme

Moja ya njia rahisi zaidi za kuona Context ikifanya kazi ni kubadilisha theme. Hivi ndivyo unavyoweza kuiunganisha bila kuruka maelezo muhimu.

Kwanza, tengeneza faili ya ThemeContext.js. Ita React.createContext() na uhifadhi matokeo yake. Kisha jenga component ya ThemeProvider inayodhibiti theme ya sasa kwa kutumia useState au useReducer. Funika watoto (children) kwenye Provider ya context yako, ukipitisha object inayohusisha theme ya sasa na kazi (function) ya kuibadilisha. Toa (export) ThemeProvider na context object yenyewe.

Pili, nenda kwenye sehemu ya kuingilia (entry point) ya app yako. Import ThemeProvider na ufunike application yako nzima nayo. Ukiruka hatua hii, kitu chochote kitakachojaribu kusoma context baadaye kitaona thamani ya kawaida (default value) tu.

Tatu, ndani ya component ya Header au Content, import context object na useContext. Ita Hook hiyo, chukua (destructure) theme na function ya kubadilisha, na utumie CSS classes zako kulingana na hali hiyo. Ongeza button inayoiita function hiyo ya kubadilisha. Component haipokei prop ya theme kutoka kwa mzazi wake. Inapata mawimbi moja kwa moja kutoka hewani.

Prop Drilling, Context, au Redux?

Kuchagua kati ya zana hizi si suala la uaminifu zaidi, bali ni kuhusu muundo wa state yako.

Prop drilling ni sawa kabisa kwa kina cha ngazi mbili au tatu. Ni wazi, rahisi kufuatilia kwenye IDE yako, na inafanya utegemezi (dependencies) uonekane wazi. Matatizo huanza kuonekana unapoanza kupitisha prop ile ile kupitia tabaka sita au saba.

Context API inakuja pamoja na React yenyewe. Hii ina maana hakuna ongezeko la ukubwa wa bundle na hakuna mipangilio ya nje. Inasimamia state ya kimataifa (global state) ya wastani au ndogo vizuri sana, hasa data ambayo haibadiliki mara kwa mara kama vile mandhari (themes) au wasifu wa mtumiaji.

Redux inahitaji kusakinisha maktaba (libraries) za ziada na kuandika boilerplate. Inalipa matunda wakati mantiki ya state yako inapokuwa tata, wakati sehemu mbalimbali za state zinapoingiliana kwa njia za kina, au wakati unahitaji time-travel debugging na middleware. Kwa data rahisi za kimataifa, Redux ni nyingi mno (overkill).

Ukweli wa Utendaji (Performance) Ambao Hakuna Anayezungumzia

Hapa ndipo penye changamoto inayotofautisha utekelezaji wa junior na senior. Wakati thamani ya Context Provider inapobadilika, kila component inayotumia context hiyo inajirendea (re-renders). Haijalishi kama sehemu mahususi ambayo component hiyo inaihitaji imebaki vilevile. React inaona rejea (reference) mpya na kupanga mchakato wa kusasisha (update).

Ukimwaga state ya programu yako nzima kwenye StoreContext moja kubwa, kwa hakika umeunganisha UI yako nzima pamoja. Kubadilisha mpangilio wa mandhari (theme) kutafanya shopping cart yako, chati za dashboard yako, na orodha ya arifa zako zijirendee tena. Hilo ni kazi isiyo ya lazima.

Gawanya context zako kwa mujibu wa domain. Weka ThemeContext kwa ajili ya mipangilio ya kuonekana, UserContext kwa ajili ya data ya wasifu, na CartContext kwa ajili ya state ya biashara. Ikiwa mtumiaji atabadilisha jina lake la kuonyeshwa, kichwa cha habari (header) chako kitasasishwa bila kugusa gridi ya bidhaa. Pia, kuwa mwangalifu na kile unachopitisha kwenye prop ya value ya Provider. Ukipitisha object literal { theme, toggleTheme } moja kwa moja wakati wa render, unaunda rejea mpya kila wakati wa render na kusababisha masasisho yasiyo ya lazima. Imarisha muundo huo kwa kutumia useMemo ikiwa thamani hiyo ina kazi (functions) au data isiyo ya msingi (non-primitive data).

Makosa Yanayopoteza Saa Nyingi

Makosa mawili huwakuta timu mara kwa mara.

Kusahau ku-export context object. Ni rahisi ku-export component ya ThemeProvider na kisha kujaribu kuita useContext(ThemeProvider). Hivyo ndivyo isivyoendavyo. Hook inahitaji context object inayotolewa na createContext, siyo component inayofunika (wrapper component). Ikiwa uta-export Provider pekee, watumiaji wako (consumers) hawatakuwa na kitu cha ku-import.

Kuita useContext nje ya Provider yake. Hook inarudisha thamani ya asili (default value) uliyopitisha kwenye createContext. Ikiwa hukuipitisha thamani ya asili, utapata undefined. Ikiwa mti wa component (component tree) unatoa consumer juu zaidi kwenye DOM kuliko Provider, au ikiwa Provider haipo kabisa, data yako haitafika. Hakikisha tena kwamba faili yako ya index au root inazunguka (wraps) programu nzima.

Hitimisho la Kweli

React Context si mapinduzi ya usimamizi wa state. Ni chombo mahususi kwa ajili ya tatizo fulani la nafasi: kufikisha data kwenye component zilizo mbali bila kugeuza kila tabaka kuwa ofisi ya posta. Itumie kwa data za kweli za kimataifa, gawanya context zako kwa mujibu wa domain ili kulinda utendaji wa render, na kila wakati zunguka mti wako na Provider sahihi kabla ya kujaribu kusoma ishara (signal). Ukizoea tabia hizo, miti yako ya component itabaki safi, ya haraka, na rahisi kueleweka.