Poznaliśmy już refy, forwardowanie refów, imperative handle oraz portale, najwyższa pora zobaczyć createRoot z biblioteki React-dom i postarać się zrozumieć, co się tam dzieje.

Ok, wiemy, że mamy plik index.html, w którym mamy m. in root, do którego jest ładowany RFC App:

<!DOCTYPE html>
<html>
  <head><title>My app</title></head>
  <body>
    <h1>Welcome to my hybrid app</h1>
    <div class="parent">
      <div class="sidebar">
        This is server non-React markup
        <div id="sidebar-content"></div>
      </div>
      <div id="root"></div>
    </div>
  </body>
</html>

Wiemy też, że ten główny RFC App żyje w root, ale może tworzyć portale do elementów poza root. Może tam ładować html, albo wręcz całe komponenty JSX, które na poziomie hierarchii komponentów będą żyły w swoim rodzicu, ale na poziomie hierarchii DOM renderowanego funkcjonalnego HTMLa (czyli z JS) będą żyły tam, gdzie je przeteleportujemy.

Ok, ale co to jest ten root. Cóż, tak wygląda index.js:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.js';
import './styles.css';

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

Postarajmy się to zrozumieć:

  • Portale miały miejsce, gdzie żyje ich apka i komponent nadrzędny, one tylko pewne komponenty teleportowały poza ten root na poziomie drzewa DOM
  • Sam komponent nadrzędny, sam mount komponentu nadrzędnego wymaga dwóch rzeczy:
    • utworzenia root, poprzez funkcję, do której przekazujemy selektor z index.html
    • wywołania na root funkcji render, do której przekazujemy komponent nadrzędny, który ma być renderowany

Czyli tak, createRoot sprawia, że w danym miejscu może żyć aplikacja reacta. Metoda render renderuje tam komponent nadrzędny i wszystkie jego dzieci. Niektóre dzieci mogą eksportować swój render albo jego część poprzez portale, na poziomie hierarchii komponentów pozostając nadal w swoich rodzicach.

I poza metodą render mamy też metodę unmount, możemy zrobić unmount całej apki. Możemy też, na poziomie index.js, zmieniać co ma być komponentem nadrzędnym albo zmieniać jakieś jego właściwości.

Komponent nadrzędny:

export default function App({counter}) {
  return (
    <>
      <h1>Hello, world! {counter}</h1>
      <input placeholder="Type something here" />
    </>
  );
}

Teraz index.js:

import { createRoot } from 'react-dom/client';
import './styles.css';
import App from './App.js';

const root = createRoot(document.getElementById('root'));

let i = 0;
setInterval(() => {
  root.render(<App key={i} counter={i} />);
  i++;
}, 1000);

Ja tutaj poleciałem po bandzie, bo ustawiłem App key, zatem co sekundę ten komponent jest re-mountowany z nową treścią. Chciałem sprawdzić, czy tak można.

Dokumentacja Reacta podaje nieco mniej dziwny przykład:

import { createRoot } from 'react-dom/client';
import './styles.css';
import App from './App.js';

const root = createRoot(document.getElementById('root'));

let i = 0;
setInterval(() => {
  root.render(<App counter={i} />);
  i++;
}, 1000);

I tutaj na początku render zrobi mount komponentu i mount render, ale za każdym innym obrotem interwału render będzie powodował diff-render (sam to tak nazywam, dokumentacja ma pojęcia initial render i re-render, ale to jakiś bełkot, który niewiele mówi).

Warto też zwrócić uwagę, że elementy, do których mamy tworzyć root, muszą być puste. Metoda render wyczyści wszystko, co się tam znajdowało. Jedynie w przypadku, gdy mamy render, nie robiliśmy root.unmount i jeszcze raz robimy render będzie po prostu diffing, zamiast unmounta.

Oczywiście jak chcemy unmount możemy ustawić key, wielokrotnie już to robiliśmy wewnątrz projektów Reacta.

Ok, teraz StrictMode. To jest tylko na produkcji i to jest z myślą o niedoświadczonych developerach, którzy nie wiedzą, co piszą. Generalnie każdy RFC ma być taki, że po pierwsze z takimi samymi argumentami zawsze da ten sam wynik, po drugie odpalony kilka razy pod rząd albo jeden raz również da taki sam wynik.

I StrictMode odpala każdy komponent dwa razy, co sprawia, że jak gdzieś zawaliliśmy jakiś cleanup albo coś, to to wyjdzie. Więcej Reacta niedługo.