Jak pisać kod, który React Compiler potrafi zoptymalizować

W poprzednim wpisie pokazywałam Wam narzędzie
👉 React Compiler Playground

które pozwala zobaczyć jak React Compiler przekształca nasz kod.

Dzisiaj pójdziemy krok dalej i zastanowimy się:

jak pisać kod, który kompilator będzie w stanie dobrze zoptymalizować.

Choć React Compiler potrafi zrobić naprawdę dużo, to nadal istnieją pewne wzorce kodu, które działają z nim znacznie lepiej niż inne.

1. Unikaj mutowania danych

React Compiler najlepiej działa wtedy, gdy dane są niemutowalne.
Czyli zamiast zmieniać istniejący obiekt – tworzymy nowy.

Źle:

const addItem = (list, item) => {
  list.push(item);
  return list;
}

Lepiej:

const addItem = (list, item) => {
  return [...list, item];
}

Dlaczego to ważne?

Ponieważ kompilator musi być w stanie łatwo wykryć czy dane się zmieniły.
Mutowanie obiektów bardzo to utrudnia.

2. Pisz czyste funkcje

Komponenty React najlepiej optymalizują się wtedy, gdy są deterministyczne – czyli dla tych samych propsów zwracają zawsze ten sam wynik.

Źle:

const Greeting = ({ name }) => {
  console.log("render");
  return <div>Hello {name}</div>;
}

Lepiej:

const Greeting = ({ name }) => {
  return <div>Hello {name}</div>;
}

Efekty uboczne w trakcie renderu utrudniają kompilatorowi analizę komponentu.

3. Trzymaj logikę renderowania w jednym miejscu

Czasami spotyka się kod, który ukrywa logikę renderowania w wielu funkcjach pomocniczych.

Przykład:

const renderTitle = (title) => {
  return <h1>{title}</h1>;
}

const Page = ({ title }) => {
  return <div>{renderTitle(title)}</div>;
}

Choć taki kod jest poprawny, to w praktyce kompilator łatwiej analizuje kod, który jest bliżej JSX-a.

Często lepiej więc napisać:

const Page = ({ title }) => {
  return (
    <div>
      <h1>{title}</h1>
    </div>
  );
}

4. Nie przesadzaj z useMemo i useCallback

To może być zaskakujące.

Przez lata uczono nas, że powinniśmy dodawać:

  • useMemo
  • useCallback

wszędzie tam, gdzie może pojawić się problem z renderowaniem.

Tymczasem React Compiler często potrafi zrobić to sam.

Czyli zamiast:

const value = useMemo(() => computeSomething(data), [data]);

możemy po prostu napisać:

const value = computeSomething(data);

A kompilator zdecyduje czy memoizacja jest potrzebna.

5. Unikaj dynamicznych struktur zależnych od renderu

Niektóre konstrukcje utrudniają analizę kodu.

Przykład:

const handlers = {
  click: () => setCount(count + 1)
};

Lepszy wariant:

const handleClick = () => {
  setCount(c => c + 1);
}

Czytelny kod bardzo pomaga kompilatorowi zrozumieć co się zmienia i kiedy.

6. Staraj się pisać prosty kod

To może brzmieć banalnie, ale React Compiler naprawdę preferuje kod, który jest:

  • przewidywalny
  • deklaratywny
  • pozbawiony sprytnych trików

Przykład:

items.map(item => <Item key={item.id} {...item} />)

jest dla kompilatora znacznie łatwiejszy do analizy niż skomplikowane funkcje generujące JSX.

Mała wskazówka

Najlepszym sposobem na sprawdzenie czy nasz kod jest „przyjazny” dla kompilatora jest… po prostu wklejenie go do

👉 React Compiler Playground

i sprawdzenie co się stanie.

Czasami okazuje się, że niewielka zmiana w strukturze kodu pozwala kompilatorowi wykonać dużo lepszą optymalizację.

You might also like