Kā React atkārtotā renderēšana sadarbojās ar Context?
Šajā rakstā jūs uzzināsiet par React renderēšanas noklusējuma darbību un konteksta izmantošanu. Jūs uzzināsiet, kā novērst nevajadzīgu augstākā līmeņa atkārtotu renderēšanu, izmantojot React.memo, un kā JavaScript darbojas objektu atsauces. Jūs arī uzzināsiet, kā izmantot useMemo āķi, lai nodrošinātu, ka objektu atsauces nemainās atkārtotas renderēšanas laikā.
Līdz šim esat uzzinājis, ka tad, kad komponents patērē kādu konteksta vērtību un šī konteksta vērtība mainās, šis komponents tiek renderēts atkārtoti.
Bet kas notiek ar visiem komponentiem starp tiem? Vai React ir pietiekami gudrs, lai tikai atkārtoti atveidotu patērētājus un apietu kokā esošās starpposma sastāvdaļas? Nu, kā izrādās, tas ne vienmēr notiek, un, veidojot React kontekstu, ir jābūt īpaši uzmanīgiem.
Runājot par React renderēšanas noklusējuma darbību, ja komponents tiek renderēts, React rekursīvi atkārtoti atveidos visus savus atvases neatkarīgi no rekvizītiem vai konteksta. Ilustrēsim šo punktu ar piemēru, kas izmanto kādu kontekstu.
Iedomājieties šādu komponentu struktūru, kur augstākā līmeņa komponents augšpusē ievada konteksta nodrošinātāju:
Lietotne (ContextProvider) > A > B > C
const App = () => {
return (
<AppContext.Provider>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = () => <ComponentB />;
const ComponentB = () => <ComponentC />;
const ComponentC = () => null;
Ja kāda iemesla dēļ tiek atkārtoti renderēts attālākais lietotnes komponents, visi ComponentA, ComponentB un ComponentC komponenti arī tiks atkārtoti renderēti šādā secībā:
Lietotne (ContextProvider) > A > B > C
Ja daži no jūsu augstākā līmeņa komponentiem ir sarežģīti, tas var izraisīt veiktspējas traucējumus. Lai mazinātu šo problēmu, varat izmantot augstākā līmeņa API React.memo().
Ja jūsu komponents nodrošina tādu pašu rezultātu, izmantojot tos pašus rekvizītus, varat to iekļaut izsaukumā uz React.memo, lai uzlabotu veiktspēju, saglabājot rezultātu atmiņā.
Memoization ir programmēšanas paņēmiens, kas paātrina veiktspēju, saglabājot dārgu funkciju izsaukumu atgriešanas vērtības.
Tas nozīmē, ka React izlaidīs komponenta renderēšanu un atkārtoti izmantos pēdējo renderēto rezultātu. Šis ir niecīgs ComponentA gadījums, jo tas nesaņem nekādus rekvizītus.
const KomponentsA = React.memo(() => <ComponentB />);
React.memo kā pirmo argumentu izmanto komponenta definīciju. Neobligātu otro argumentu var iekļaut, ja vēlaties norādīt kādu pielāgotu loģiku, kas nosaka, kad komponents ir jāpārveido, pamatojoties uz iepriekšējiem un pašreizējiem rekvizītiem.
Pēc šīs nelielās pielāgošanas jūs novērsīsit renderēšanu visās ComponentA, ComponentB un ComponentC, ja lietotnes komponents tiek atkārtoti renderēts.
const App = () => {
return (
<AppContext.Provider>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = React.memo(() => <ComponentB />);
const ComponentB = () => <ComponentC />;
const ComponentC = () => null;
Labā prakse ir ietīt React komponentu tūlīt aiz konteksta nodrošinātāja, izmantojot React.memo.
Reālās dzīves lietojumprogrammās jums būs jānodod vairāki dati kā konteksta vērtība, nevis viens primitīvs, piemēram, virkne vai skaitlis, tāpēc jūs, visticamāk, strādāsit ar JavaScript objektiem.
Tagad saskaņā ar React konteksta noteikumiem visi patērētāji, kas ir pakalpojumu sniedzēja pēcnācēji, atkārtoti renderēs ikreiz, kad mainīsies pakalpojumu sniedzēja vērtības piedāvājums.
Apskatīsim šādu scenāriju, kas balstīts uz iepriekšējo piemēru, kur ievadāmā konteksta vērtība ir definēta kā objekts, ko sauc par vērtību ar diviem rekvizītiem “a” un “b”, kas ir abas virknes. Turklāt ComponentC tagad ir konteksta patērētājs, tāpēc ikreiz, kad mainās nodrošinātāja vērtības piedāvājums, ComponentC atveidos no jauna.
const App = () => {
const value = {a: 'hi', b: 'bye'};
return (
<AppContext.Provider value={value}>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = React.memo(() => <ComponentB />);
const ComponentB = () => <ComponentC />;
const ComponentC = () => {
const contextValue = useContext(AppContext);
return null;
};
Iedomājieties, ka nodrošinātāja sniegtā vērtība tiek mainīta uz {a: ‘sveiki’, b: ‘attā’}.
Ja tā notiek, atkārtotas renderēšanas secība būtu šāda:
App (ContextProvider) -> C
Tas viss ir labi un sagaidāms, taču kas notiktu, ja lietotnes komponents tiek atkārtoti renderēts kāda cita iemesla dēļ un nodrošinātāja vērtība nemaz nemainās, jo joprojām ir {a: ‘čau’, b: ‘bye’}?
Jums var būt pārsteigums, uzzinot, ka atkārtotas renderēšanas secība ir tāda pati kā iepriekš:
App (ContextProvider) -> C
Pat ja šķiet, ka nodrošinātāja vērtība nemainās, ComponentC tiek atveidots atkārtoti.
Lai saprastu, kas notiek, jums jāatceras, ka JavaScript tālāk norādītais apgalvojums ir patiess:
{a: ‘čau’, b: ‘attā’} !== {a: ‘čau’, b: ‘attā’}
Tas ir tāpēc, ka objektu salīdzināšana JavaScript tiek veikta ar atsauci. Katru reizi, kad lietotnes komponentā notiek jauna atkārtota renderēšana, tiek izveidots jauns vērtības objekta gadījums, kā rezultātā pakalpojumu sniedzējs veic salīdzinājumu ar tā iepriekšējo vērtību un nosaka, ka tā ir mainījusies, tādējādi informējot visus konteksta patērētājus, ka viņiem vajadzētu atkārtoti. – renderēt.
Šo problēmu var atrisināt, izmantojot React āķi useMemo šādi.
const App = () => {
const a = 'hi';
const b = 'bye';
const value = useMemo(() => ({a, b}), [a, b]);
return (
<AppContext.Provider value={value}>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = React.memo(() => <ComponentB />);
const ComponentB = () => <ComponentC />;
const ComponentC = () => {
const contextValue = useContext(AppContext);
return null;
};
Šajā piemērā pietiek pateikt, ka useMemo iegaumēs atgriezto vērtību no funkcijas, kas nodota kā pirmais arguments, un veiks aprēķinu atkārtoti tikai tad, ja kāda no vērtībām tiks nodota masīvā kā otrā argumenta maiņa.
Izmantojot šo ieviešanu, ja Lietotne tiek atkārtoti renderēta kāda cita iemesla dēļ, kas nemaina nevienu no “a” vai “b” vērtībām, atkārtotas renderēšanas secība būs šāda:
App (ContextProvider)
Tas ir vēlamais rezultāts, izvairoties no nevajadzīgas atkārtotas renderēšanas ComponentC. useMemo garantē vienas un tās pašas objekta atsauces saglabāšanu vērtības mainīgajam, un, tā kā tas ir piešķirts pakalpojumu sniedzēja vērtībai, tas nosaka, ka konteksts nav mainījies un par to nav jāinformē neviens patērētājs.
Kopsavilkums:
Jūs uzzinājāt par to, kā React darbojas atkārtota renderēšana, kad tiek izmantots konteksts, un kā React.memo un useMemo API no React var palīdzēt veikt dažas optimizācijas, lai izvairītos no nevajadzīgas atkārtotas renderēšanas komponentu kokā.
Atbildēt
Lai komentētu, jums jāpiesakās sistēmā.