Vitu ishirini kwenye feed huonekana kuwa sawa kabisa. Kusogeza (scroll) ni laini kama siagi. Mteja wako anafurahi. Kisha unatoa programu kwenye production, data inafika, na ghafla unajikuta unatazama mistari elfu mbili. UI inaanza kukwama. Matumizi ya kumbukumbu (memory) yanaongezeka hadi OS inapoizima. Katika kukata tamaa, baadhi ya watengenezaji huweka kila kitu ndani ya ScrollView na kuishia hapo. Uamuzi huo kwa kawaida huzalisha hitilafu (bugs) tatu mpya kwa kila moja inayotatuliwa.
Orodha (Lists) ndizo kikwazo cha utendaji (performance bottleneck) kinachofafanua jinsi watumiaji wanavyochukulia programu yako ya React Native. Ukizifanya vizuri, programu itahisi kama ya asili (native). Ukizifanya vibaya, hata skrini nzuri zaidi itakuwa nzito na yenye kusuasua. Chanzo kikuu kwa kawaida ni kutolingana kati ya component uliyochagua na kazi unayoiomba JavaScript na UI threads kufanya. React Native inafanya kazi kwenye njia mbili. Mantiki (logic) yako ipo kwenye JS thread wakati uchoraji (painting) hutokea kwenye native UI thread. Unapofanya rendering ya orodha kubwa isivyo sahihi, njia zote mbili zinaanza kuzama kwenye mahesabu ya mpangilio (layout calculations), re-renders, na ugawaji wa kumbukumbu (memory allocations). Matokeo yake ni fremu zinazopotea, miale ya skrini iliyo wazi, na hatimaye programu kuzima (crash).
Chagua Zana Sahihi
Kuchagua component ya orodha kunapaswa kuwa uamuzi wa kimkakati wa usanifu (architectural decision), siyo jambo la kubahatisha.
ScrollView ndiyo chaguo rahisi zaidi. Inachukua kila mtoto (child) unaupa, inapakia kila mmoja kwenye kumbukumbu mara moja, na kuikabidhi pile nzima kwa native scroll engine. Hiyo ndiyo hasa unayotaka kwa maudhui mafupi na yaliyofungwa kama skrini ya mipangilio (settings screen), fomu ya kuingia (login form), au ukurasa wa maelezo ya bidhaa wenye sehemu kumi. Ni inayotabirika na rahisi kupambia (style). Changamoto ni kwamba haina virtualization. Ukijaza vitu elfu mbili, itatengeneza native views elfu mbili kwa utii. Usitumie ScrollView kwa seti kubwa au zinazobadilika za data. Ifikirie kama bango lililowekwa kwenye fremu, siyo rafu ya maktaba.
FlatList ndiyo injini kuu kwa feed ndefu na zenye muundo mmoja. Inafanya virtualization ya maudhui, ikimaanisha inapakia tu mistari ambayo kwa sasa inaonekana au iko karibu na viewport. Mtumiaji anaposogeza, FlatList inatoa (unmounts) seli zinazoondoka kwenye skrini na kuzitumia tena kwa data inayokuja. Hii inafanya matumizi ya kumbukumbu yawe thabiti bila kujali jinsi array yako inavyokua. Ikiwa unajenga timeline ya kijamii, kituo cha arifa (notification center), au mkusanyiko wowote wa kadi zinazofanana zinazosogezwa mfululizo, FlatList ndicho chaguo sahihi la msingi.
SectionList ni FlatList yenye mpangilio. Itumie wakati data yako inakuja katika makundi, kama vile kitabu cha anwani kilichopangwa alfabeti, logi ya mazoezi iliyogawanywa kwa tarehe, au orodha ya ankara iliyopangwa kwa mwezi. Inatoa vichwa vya sehemu vinavyoshikilia (sticky section headers) na inashughulikia mantiki ya uunganishaji (grouping logic) kwa ajili yako. Chini ya uendeshaji, inatumia mfumo uleule wa virtualization kama FlatList, hivyo unapata faida zilezile za kumbukumbu pamoja na muundo wa sehemu zenye vichwa.
FlashList huingia pale unapohitaji kutoa kila fremu ya mwisho kutoka kwenye kifaa. Imejengwa juu ya mfumo wa RecyclerListView, inazungusha (recycles) views kwa nguvu zaidi kuliko FlatList na inalenga kudumisha fremu sitini kwa sekunde hata kwenye vifaa vya kati. Ikiwa unajenga interface ya mazungumzo yenye ujumbe mwingi, katalogi ya bidhaa yenye kasi kubwa ya kusogeza, au skrini yoyote ambapo ulaini ni faida ya ushindani, FlashList inastahili kuongezwa. Si lazima kwa kila skrini, lakini kwa feed zinazofafanua uzoefu wa msingi, tofauti ya utendaji inahisiwa wazi.
Vizuizi vya Kawaida vya Utendaji
Kuna washukiwa watatu wa kawaida wakati orodha inapoanza kusuasua.
Kuweka (Mounting) miti mingi ya React kwa wakati mmoja ndiyo hitilafu kubwa zaidi. Wakati kila mstari ni mti tata wa component, rendering ya awali inaweza kuzuia JS thread kwa muda mrefu kiasi cha kuzalisha skrini nyeupe iliyo wazi au picha ya kwanza inayochelewa kuonekana. Mtumiaji anafungua programu na kusubiri. Hata baada ya upakiaji wa awali, mistari mizito hufanya uanzishaji wa scroll kuwa mzito kwa sababu fremu chache za kwanza zinatumika kwa kazi ya kusanidi (setup work).
Kazi nyingi sana kwa kila fremu huonekana kama kusuasua wakati wa kusogeza. Una bajeti ya takriban milisekunde kumi na sita kwa kila fremu ili kuweka animation kuwa laini. Ikiwa component ya mstari inafanya mahesabu magumu, inachambua tarehe papo hapo, au inafanya ulinganishaji wa kina wa object ndani ya render, unavunja bajeti hiyo. UI thread inapoteza fremu na mtumiaji anahisi mshtuko.
Matumizi ya kumbukumbu (memory) yaliyopitiliza ni muuaji wa kimya. Kila native view inagharimu RAM. Ongeza picha kubwa zisizoboreshwa, vivuli (drop shadows) kwenye kila kadi, au touchables zilizofungwa ndani ya nyingine, na matumizi yanazidi. Kwenye iOS, mfumo unaweza kufunga programu yako bila onyo. Kwenye Android, mtumiaji anaona ucheleweshaji ukiongezeka hadi programu ionekane haiwezi kutumika.
Orodha ya Uhakiki wa Uboreshaji (Optimization Checklist)
Tabia ndogo za kimkakati hutofautisha orodha inayofanya kazi tu na ile inayofanya kazi kwa kasi ya ajabu.
Tumia funguo (keys) thabiti. Daima pitisha utambulisho halisi kutoka kwenye seti yako ya data kwenye key prop. Usitumie kamwe index ya array. Ikiwa orodha yako inapanga upya, inachuja, au inaongeza vitu, funguo inayotegemea index itamdanganya React kuunganisha data isiyo sahihi na component iliyorejeshwa (recycled component) isiyo sahihi. Kosa hilo husababisha unmounts zisizo za lazima, kutofautiana kwa hali (state mismatches), na re-renders zinazofuatana. ID sahihi huambia React ni mstari gani hasa ulihamia wapi.
Memoize mistari (rows). Funika component yako ya mstari katika React.memo ili i-re-render tu wakati props zake zinapobadilika kweli. Bila kinga hii, update yoyote ya hali ya mzazi (parent state update) inaweza kusababisha render pass kwenye kila mstari unaoonekana, hata kama data zao ni sawa. Katika orodha ndefu inayozunguka (churns), mzunguko huo uliopotea huongezeka haraka.
Weka renderItem iwe thabiti. Epuka kufafanua function mpya moja kwa moja ndani ya renderItem prop kila wakati mzazi unapofanya render. Inline arrow function kama renderItem={({ item }) => <Row data={item} />} hutengeneza marejeo (reference) mapya kila wakati mzazi unapofanya update. FlatList itaona prop iliyobadilika na itarejesha (recycle) mstari huo bila sababu. Fafanua function ya render nje ya component au i-memoize kwa kutumia useCallback ili marejeo yabaki thabiti.
Tumia getItemLayout kila inapowezekana. Ikiwa mistari yako ina urefu uliowekwa au unaotabirika, iambie FlatList urefu huo hasa. Prop hii inaruhusu orodha kuruka hatua za gharama kubwa za vipimo vya asili (native measurement calls). Badala ya kupima kila seli baada ya kuunganishwa (mount), orodha hupiga hesabu ya nafasi kimahesabu. Tofauti hiyo ni kubwa hasa kwenye orodha zenye mamia au maelfu ya vitu, ambapo mwingiliano mwingi wa onLayout unaweza kuifanya JS thread ishindwe kufanya kazi.
Boresha picha kwa ukali (aggressively). Picha zisizo na mipaka ni sumu kwa orodha. Daima weka upana (width) na urefu (height) maalum ili tabaka la asili (native layer) liweke nafasi kabla ya picha kusomika (decodes). Kwa picha za mbali (remote images), tumia maktaba ya caching kama Expo Image au inayolingana inayoshughulikia memory caching, disk persistence, na uboreshaji wa format. Component ya kawaida ya React Native Image inafanya kazi kwa prototaipe, lakini mifumo ya uzalishaji (production feeds) inahitaji udhibiti zaidi wa kumbukumbu (memory) na hali za kupakia (loading states).
Epuka kuweka scroll containers ndani ya nyingine. Usiweke kam
