Pre nego što se vaše komponente prikažu na ekranu, React mora da ih renderuje. Razumevanje koraka u ovom procesu pomoći će vam da razmislite o tome kako se vaš kod izvršava i da objasnite njegovo ponašanje.

Naučićete:

  • Šta u React-u znači renderovanje
  • Kada i zašto React renderuje komponentu
  • Korake potrebne za prikaz komponente na ekranu
  • Zašto renderovanje ne ažurira DOM uvek

Zamislite da su vaše komponente kuvari u kuhinji, koji pripremaju ukusna jela od sastojaka. U ovom scenariju, React je konobar koji prenosi porudžbine od gostiju i donosi im njihova jela. Ovaj proces poručivanja i posluživanja UI-a ima tri koraka:

  1. Pokretanje rendera (prenos porudžbine gosta u kuhinju)
  2. Renderovanje komponente (priprema porudžbine u kuhinji)
  3. Commit-ovanje u DOM (postavljanje porudžbine na sto)
  1. React kao konobar u restoranu, prenosi porudžbine od korisnika i dostavlja ih u Kitchen komponentu.
    Pokretanje
  2. Šef kuhinje za Card daje React-u svežu Card komponentu.
    Render
  3. React donosi Card korisniku za njegov sto.
    Commit

Illustrated by Rachel Lee Nabors

Korak 1: Pokrenuti render

Postoje dva razloga da se komponenta renderuje:

  1. Inicijalni render komponente.
  2. State se promenio, bilo od komponente ili nekog od njenih roditelja.

Inicijalni render

Kad se aplikacija pokrene, morate započeti inicijalni render. Framework-ovi i sandbox-ovi često skrivaju ovaj kod, ali se on pokreće pozivanjem createRoot nad željenim DOM čvorom, a nakon toga i pozivanjem render metode sa vašom komponentom:

import Image from './Image.js';
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'))
root.render(<Image />);

Zakomentarišite root.render() poziv i vidite kako će komponenta nestati!

Ponovni renderi kad se state ažurira

Kada je komponenta inicijalno renderovana, možete pokrenuti naredne rendere ažuriranjem state-a pomoću set funkcije. Ažuriranjem state-a vaše komponente automatski stavljate render u red čekanja. (Ovo možete zamisliti kao da gost restorana poručuje čaj, dezert i ostale stvari nakon prve porudžbine, u zavisnosti od state-a žeđi i gladi.)

  1. React kao konobar u restoranu, servira Card UI korisniku, koji je predstavljen kao čovek sa kursorom na glavi. Korisnik izražava da želi roze karticu, a ne crnu!
    Ažuriranje state-a...
  2. React se vraća u Kitchen komponentu i kaže šefu kuhinje za Card da mu treba roze Card.
    ...pokreće...
  3. Šef kuhinje za Card daje React-u roze Card.
    ...render!

Illustrated by Rachel Lee Nabors

Korak 2: React renderuje vaše komponente

Kada pokrenete render, React poziva vaše komponente da shvati šta da prikaže na ekranu. “Renderovanje” je zapravo React-ovo pozivanje vaših komponenata.

  • Pri inicijalnom renderu, React će pozvati root komponentu.
  • Za naredne rendere, React će pozvati funkciju komponente čije ažuriranje state-a je pokrenulo render.

Ovaj proces je rekurzivan: ako ažurirana komponenta vrati drugu komponentu, React će renderovati tu drugu komponentu, a ako ta komponenta takođe nešto vrati, renderovaće to nešto sledeće, i tako dalje. Proces će se nastaviti dok god postoje ugnježdene komponente i React zna tačno šta treba biti prikazano na ekranu.

U narednom primeru, React će pozvati Gallery() i Image() nekoliko puta:

export default function Gallery() {
  return (
    <section>
      <h1>Inspirativne skulpture</h1>
      <Image />
      <Image />
      <Image />
    </section>
  );
}

function Image() {
  return (
    <img
      src="https://i.imgur.com/ZF6s192.jpg"
      alt="'Floralis Genérica' napravio Eduardo Catalano: ogromna metalik skulptura cveta sa reflektujućim laticama"
    />
  );
}

  • Tokom inicijalnog rendera React će kreirati DOM čvorove za <section>, <h1> i tri <img> tag-a.
  • Tokom ponovnog rendera React će izračunati koja od njihovih polja (ili nijedno) su se promenila od prethodnog rendera. Neće uraditi ništa sa tom informacijom do narednog koraka, commit faze.

Pitfall

Renderovanje mora uvek biti čist proračun:

  • Isti input-i, isti rezultat. Dobijanjem istih input-a, komponenta treba uvek da vrati isti JSX. (Kada neko poruči salatu sa paradajzom, ne bi trebao da dobije salatu sa lukom!)
  • Gleda samo svoja posla. Ne bi trebalo da menja nikakve objekte ili promenljive koji su postojali pre renderovanja. (Jedna porudžbina ne bi trebala da menja bilo koju drugu porudžbinu.)

U suprotnom, naići ćete na zbunjujuće bug-ove i nepredvidivo ponašanje dok se kompleksnost na vašem projektu povećava. U toku razvoja sa “Strict Mode”, React poziva funkciju svake komponente dvaput, što može pomoći da se uoče greške prouzrokovane nečistim funkcijama.

Deep Dive

Optimizacija performansi

Default ponašanje renderovanja svih komponenti ugnježdenih u ažuriranu komponentu nije optimalno za performanse ako je ažurirana komponenta dosta visoko u stablu. Ako naiđete na problem sa performansama, postoji nekoliko opcija da to rešite opisanih u sekciji Performanse. Nemojte optimizovati prerano!

Korak 3: React commit-uje promene na DOM

Nakon renderovanja (pozivanja) vaših komponenata, React će izmeniti DOM.

  • Za inicijalni render, React će koristiti appendChild() DOM API da postavi sve DOM čvorove koje je kreirao na ekran.
  • Za ponovne rendere, React će primeniti minimum neophodnih operacija (izračunatih tokom renderovanja!) da bi učinio da se DOM poklapa sa najnovijim rezultatom renderovanja.

React menja DOM čvorove samo ako postoji razlika između rendera. Na primer, ovde je komponenta koja se ponovo renderuje sa drugačijim props-ima koje dobija od roditelja svake sekunde. Primetite da možete dodati tekst u <input>, menjajući value, i da taj tekst neće nestati kad se komponenta ponovo renderuje:

export default function Clock({ time }) {
  return (
    <>
      <h1>{time}</h1>
      <input />
    </>
  );
}

Ovo radi jer tokom poslednjeg koraka, React jedino ažurira sadržaj <h1> sa novim time. On vidi da se <input> pojavljuje u JSX-u na istom mestu kao prethodni put, pa React ne dira <input>—niti njegov value!

Epilog: Browser slikarstvo

Nakon što se renderovanje završi i React ažurira DOM, browser će ponovo oslikati ekran. Iako je ovaj proces poznat kao “browser renderovanje”, mi ćemo ga osloviti sa “slikarstvo” da bi izbegli zabunu kroz dokumentaciju.

Browser slika 'mrtva priroda sa elementom kartice'.

Illustrated by Rachel Lee Nabors

Recap

  • Svako ažuriranje ekrana u React aplikaciji se dešava u tri faze:
    1. Pokretanje
    2. Render
    3. Commit
  • Možete koristiti Strict Mode da pronađete greške u komponentama
  • React ne dira DOM ako je rezultat renderovanja isti kao prethodni put