Головна / Статті / Продуктивність React за межами ручного використання memo: структура та планування

Продуктивність React за межами ручного використання memo: структура та планування

Порада з часів компіляторів: розміщуйте стан у одному місці, виділяйте термінову роботу, відправляйте менше JS, а потім мемоайзуйте виявлені проблемні ділянки.

803 слів

Протягом багатьох років поради щодо продуктивності React полягали у тому, щоб обгортати все за допомогою API memo:

const value = useMemo(() => expensiveCalculation(data), [data]);
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);export default React.memo(Component);
function ProductList({ products, onSelect }) {
  const processed = useMemo(
    () => processProducts(products),
    [products]
  );
  const handleSelect = useCallback(
    (id) => onSelect(id),
    [onSelect]
  );  return (
    <List
      products={processed}
      onSelect={handleSelect}
    />
  );
}
App
 │
 ├── Header
 ├── Sidebar
 ├── Search
 ├── ProductList
 └── Footer
function App() {
  const [query, setQuery] = useState("");
  // large component tree
}
App
 │
 ├── Header
 ├── Sidebar
 ├── Search
 │    └── query state
 ├── ProductList
 └── Footer
const [query, setQuery] = useState("");
const [isPending, startTransition] = useTransition();
function handleChange(event) {
  const value = event.target.value;  setQuery(value);  startTransition(() => {
    setSearchResults(filterProducts(value));
  });
}
User input
    │
    ├── urgent ───────► keep UI responsive
    │
    └── non-urgent ───► transition
const AnalyticsDashboard = lazy(
  () => import("./AnalyticsDashboard")
);
Initial JavaScript
       │
       ▼
┌─────────────────────┐
│ Everything          │
│ Dashboard           │
│ Analytics           │
│ Editor              │
│ Admin               │
└─────────────────────┘
Initial load
    │
    ├── Core UI
    │
    └── Later
          ├── Analytics
          ├── Editor
          └── Admin
"This component renders often."
        │
        ▼
Add useMemo
"This component renders often."
        │
        ▼
Why?
        │
 ┌──────┼───────────┐
 ▼      ▼           ▼
State  Expensive   Large
flow   work        subtree
 │      │           │
 ▼      ▼           ▼
Colocate  Optimize  Restructure
1. Measure
      ↓
2. Find the expensive work
      ↓
3. Fix component architecture
      ↓
4. Reduce unnecessary JavaScript
      ↓
5. Prioritize updates correctly
      ↓
6. Let React Compiler handle memoization
      ↓
7. Manually optimize only when evidence says you should

Лише мемоізація не вирішує проблеми повільних додатків. Навіть ідеально мемоізована структура може працювати повільно через надмірний обсяг даних, термінові оновлення, які виконують неважливі завдання, або велику кількість коду JavaScript у основному потоці.

React Compiler змінює стандарт

Компілятор автоматизує багато процедур мемоізації. Це дозволяє зосередитися на структурі та плануванні, а не на ручному використанні useMemo у кожному місці.

По-перше: розміщуйте дані ближче до місця їх використання

Високий рівень стану в дереві змушує переробляти всі піддерева. Розміщуйте стан разом із листками, які його потребують; піднімайте його лише тоді, коли це необхідно для спільного використання.

По-друге: не змушуйте термінові оновлення виконувати неважливі завдання

Зберігайте чутливість до натискання клавіш та анімацій. Відкладайте неважливі завдання за допомогою переходів чи відкладених значень, щоб натискання клавіш не блокувалися дорогими фільтрами.

По-третє: перегляньте JavaScript, який ви використовуєте

Великі цикли синхронізації, дорогі форматувальники та необмежені списки домінують ще до того, як це зробить механізм узгодження React. Аналізуйте JavaScript, а не лише те, що показують інструменти React DevTools.

То коли варто використовувати useMemo?

Він все ще корисний для забезпечення стабільності посилань між дочірніми елементами, які не передають пропси, а також для дуже витратних чистих обчислень — після їх вимірювання. Не як стандартний інструмент для кожного значення.

Новий підхід до продуктивності в React

Структура → планування → відправка меншої кількості JS → потім мікромемоізація найбільш використовуваних ділянок. Мемоізація за допомогою компілятора є допоміжним засобом, а не заміною правильного проектування.

Додайте бюджет продуктивності до PR-запитів: час взаємодії до наступного оновлення інтерфейсу для основної форми, а також знімок профілю React для відомого навантажувального шляху.

Списки повинні віртуалізуватися перед тим, як мемоізувати кожен рядок. Мемоізація при відображенні 10 тис. рядків все одно призводить до втрат продуктивності.

Додайте бюджет продуктивності до PR-запитів: час взаємодії до наступного оновлення інтерфейсу для основної форми, а також знімок профілю React для відомого навантажувального шляху.

Списки повинні віртуалізуватися перед тим, як мемоізувати кожен рядок. Мемоізація при відображенні 10 тис. рядків все одно призводить до втрат продуктивності.

Додайте бюджет продуктивності до PR-запитів: час взаємодії до наступного оновлення інтерфейсу для основної форми, а також знімок профілю React для відомого навантажувального шляху.

Списки повинні віртуалізуватися перед тим, як мемоізувати кожен рядок. Мемоізація при відображенні 10 тис. рядків все одно призводить до втрат продуктивності.

Додайте бюджет продуктивності до PR-запитів: час взаємодії до наступного оновлення інтерфейсу для основної форми, а також знімок профілювання React для відомого навантажувального маршруту.

Списки повинні віртуалізуватися перед тим, як мемоїзувати кожен рядок. Мемоїзація під час завантаження списку з 10 тис. рядків все одно призводить до проблем.

Додайте бюджет продуктивності до PR-запитів: час взаємодії до наступного оновлення інтерфейсу для основної форми, а також знімок профілювання React для відомого навантажувального маршруту.

Списки повинні віртуалізуватися перед тим, як мемоїзувати кожен рядок. Мемоїзація під час завантаження списку з 10 тис. рядків все одно призводить до проблем.

Додайте бюджет продуктивності до PR-запитів: час взаємодії до наступного оновлення інтерфейсу для основної форми, а також знімок профілювання React для відомого навантажувального маршруту.

Списки повинні віртуалізуватися перед тим, як мемоїзувати кожен рядок. Мемоїзація під час завантаження списку з 10 тис. рядків все одно призводить до проблем.