Анонсовано React 18! Поглянемо, що має змінитись

12 хв. читання

Представлений наприкінці 2020 року React 17 не приніс багато нових можливостей. Натомість в ньому було багато вдосконалень, виправлень та закладено основи для майбутніх оновлень. Все для плавного впровадження подальших змін.

Саме так ми переходимо до React 18. У своєму недавньому дописі в блозі команда React оголосила про плани щодо наступної версії React та її нових функцій. Також йшлося про графік випуску, загальнодоступну альфа-версію та навіть про створену робочу групу для обговорень і вдосконалення React 18.

Загалом довкола React кипить робота, тому гайда занурмося глибше і розглянемо всі анонси та деякі додаткові подробиці!

Робоча група React 18

Перш ніж заглибитися у чудові нові можливості, нам варто звернути увагу на робочу групу React 18, оскільки такий підхід застосовується для розробки React вперше.

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

Там ви знайдете різні ідеї, огляд можливостей, результати досліджень від команди React та багато іншого — справжня золота жила інформації про React 18.

Знову ж таки, робоча група React 18 — це перша така спроба залучити спільноту та розробників екосистем до створення наступного випуску React. Як це вплине на результат? Нам доведеться почекати, щоб дізнатися.

Нові можливості

На відміну від попередньої версії, у React 18, схоже, буде досить багато нових функцій. Деякі з них є звичайними поліпшеннями; інші вдосконалюватимуть паралельний режим React. У кожному разі буде багато нового, а перелік вдосконалень ще цілком може розширитись у процесі розробки!

Автоматичне групування (Batching)

Почнемо з продуктивності. Нова версія принесе значні вдосконалення для автоматичного групування (batching).

У попередніх версіях React кілька оновлень стану вже групувалися в одне, щоб скоротити кількість повторень оновлення інтерфейсу. Однак це працювало лише для обробників подій DOM, але не для промісів, тайм-аутів чи інших обробників.

const App = () => {
  const [firstCount, setFirstCount] = useState(0);
  const [secondCount, setSecondCount] = useState(0);
  const handleClick = () => {
    setFirstCount((count) => count + 1); // No re-render yet
    setSecondCount((count) => count + 0.5); // No re-render yet
    // Re-render (updates batched)
  };
  /*
  const alternativeHandleClick = () => {
    Promise.resolve().then(() => {
      setFirstCount((count) => count + 1); // Re-render
      setSecondCount((count) => count + 0.5); // Re-render
    });
  };
  */
  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <span
        style={{
          color: firstCount % 2 === 0 ? "blue" : "black",
        }}
      >
        {secondCount}
      </span>
    </div>
  );
};

У версії React 18 стани групуватимуться, де б вони не відбувались, якщо це безпечно. Це поліпшить роботу без будь-якого додаткового коду.

У цьому обговоренні ви можете дізнатись, як відійти від групування подій застарілим методом ReactDOM.flushSync() у компонентах, заснованих на класах, та багато іншого.

Зміни Strict Mode

Наступною зміною є деякі доповнення у Strict Mode, включно з новою поведінкою, яка називається «strict effects». Це подвійний виклик ефектів — зокрема mount і unmount.

Додаткові перевірки тут потрібні для тестування кількох циклів mount/unmount. Це забезпечує і стійкість компонентів, і правильну поведінку зі швидким оновленням (Fast Refresh) під час розробки (коли компоненти додаються/від'єднуються для оновлення). А ще це потрібно для нового Offscreen API, який зараз в розробці.

Offscreen API поліпшить швидкодію, оскільки ховатиме, а не від'єднуватиме компоненти, зберігаючи їхній стан, а далі викликатиме ефекти mount/unmount. Це відіграватиме вирішальну роль в оптимізації компонентів, таких як вкладки, віртуалізовані списки тощо.

Докладніше про Strict Effects тут.

Root API

Що стосується можливостей API для користувачів: функція render — одна з перших, яку запускає React-застосунок, — буде замінена на createRoot.

Новий API є шлюзом для доступу до нових можливостей React 18. Він працюватиме поряд із застарілим API, щоб прийняття було поступовим і можна було легко порівняти їхню швидкодію.

Новий Root API також відрізняється продуманішим синтаксисом.

import ReactDOM from "react-dom";
import App from "App";
const container = document.getElementById("app");
// Old
ReactDOM.render(<App />, container);
// New
const root = ReactDOM.createRoot(container);
root.render(<App />);

Зверніть увагу, що тепер root вашого React-застосунку відокремлений. Root, який є покажчиком структури даних верхнього рівня, прикріпленим до елемента DOM, раніше був непрозорим для користувача функції render.

Спочатку потрібно створити root за допомогою функції createRoot, а потім викликати з нього метод render. Це дає нові можливості та робить оновлення зрозумілішим і простішим.

Новий API також змінює спосіб роботи зворотного виклику render та функції hydrate. Через труднощі з правильними таймінгами аргумент зворотного виклику повністю вилучається. Замість нього ви повинні використовувати, наприклад, timeout або ref callback з root.

// Old
ReactDOM.render(<App />, container, () => console.log("renderered"));
// New
const App = ({ callback }) => {
  return (
    <div ref={callback}>
      <h1>Hello World</h1>
    </div>
  );
}
const root = ReactDOM.createRoot(container);
root.render(<App callback={() => console.log("renderered")} />);

Щодо hydrate, то вона перетворюється з окремої функції на опцію конфігурації, і це робить її «розумнішою».

// Old
ReactDOM.hydrate(<App />, container);
// New
const root = ReactDOM.createRoot(container, { hydrate: true });
root.render(<App />);

Пов'язане з цим оновленням обговорення читайте тут.

Паралельний рендеринг

Безсумнівно, найбільшим оновленням React 18 буде «паралельний режим», або, як це зараз називається — «паралельний рендеринг».

Зміна назви важлива: вона повідомляє про ймовірність нових можливостей паралелізму. Йдеться про те, щоб впроваджувати їх поступово, без перезаписування коду та у зручний для вас час.

Нові API

З новими можливостями з'являються нові API. У разі одночасної візуалізації всі вони рівноправні та охоплюють переходи стану, оновлення Suspense та нові хуки.

  • startTransition

React 18 представляє новий API для обробки значних оновлень стану, як-от отримання даних або фільтрування списків. У таких випадках проста зміна стану спричиняє негайне оновлення, сповільнюючи інтерфейс.

Для боротьби з цим існує новий API у вигляді функції startTransition. Його завдання — позначити оновлення стану як переходи, щоб їхня обробка не була терміновою.

import { startTransition } from "react";
// ...
// Urgent -> show updated input
setInputValue(input);
// Transition (non-urgent) -> show search
startTransition(() => {
  setSearchQuery(input);
});

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

Окрім startTransition, новий хук useTransition надасть відомості про те, чи є у черзі цей перехід і дозволить встановити додатковий тайм-аут після переходу.

const App = () => {
  // ...
  const [isPending, startTransition] = useTransition({ timeoutMs: 2000 });
  startTransition(() => {
    setSearchQuery(input);
  });
  // ...
  return (
    <span>
      {isPending ? " Loading..." : null}
      {/* ... */}
    </span>
  );
};

Потім ви можете скористатися цими відомостями для завантаження інтерфейсу, реалізації налаштовуваної обробки тощо. Докладніше про переходи, їхнє порівняння із setTimeout та іншими випадками читайте тут.

  • useDeferredValue

Продовжуємо тему відкладених зміни значення і отримуємо новий хук useDeferredValue.

import { useDeferredValue } from "react";
// ...
const [text, setText] = useState("text");
const deferredText = useDeferredValue(text, { timeoutMs: 2000 });
/

Хук поверне відкладену версію отриманого значення, яке буде «відставати» від оригінального для надання тайм-ауту.

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

  • SuspenseList

Насамкінець, з'явиться новий компонент <SuspenseList>. Він створює порядок, у якому безпосередньо вкладені (на 1-му рівні) компоненти <Suspense> та <SuspenseList>.

import { Suspense, SuspenseList } from "react";
const App = () => {
  return (
    <SuspenseList revealOrder="forwards">
      <Suspense fallback={"Loading..."}>
        <ProfilePicture id={1} />
      </Suspense>
      <Suspense fallback={"Loading..."}>
        <ProfilePicture id={2} />
      </Suspense>
      <Suspense fallback={"Loading..."}>
        <ProfilePicture id={3} />
      </Suspense>
    </SuspenseList>
  );
};

Компонент призначений для обробки випадків, коли, до прикладу, отримані дані надходять в непередбачуваному порядку. Завдяки <SuspenseList> можна керувтаи цими даними і зберегти користувацький інтерфейс.

Додаткові відомості, зокрема про налаштування поведінки <SuspenseList> за допомогою властивостей, можна знайти в документації про розробку (яка ще триває). \t

Вдосконалення Suspense

У поєднанні з <SuspenseList> та іншими оновленнями паралельного рендерингу є деякі вдосконалення роботи Suspense.

Найбільше вдосконалення Suspense — він нарешті стає стабільною функцією, з великими архітектурними змінами під капотом та новою назвою — «Concurrent Suspense». Але термінологія переважно призначена для того, щоб розмежувати версії функцій у контексті міграції. Зміни, помітні користувачеві, тут мінімальні.

Найважливіша зміна для користувачів (хоча і досі мінімальна) пов'язана з рендерингом елементів одного рівня з «підвішеним» компонентом.

const App = () => {
  return (
    <Suspense fallback={<Loading />}>
      <SuspendedComponent />
      <Sibling />
    </Suspense>
  );
};

Якщо ввести цей код у React 17, відбудеться негайне додавання <Sibling/>, виклик його ефектів та його приховування після цього.

React 18 виправляє це, не додаючи компонент взагалі, а чекаючи, поки виконається <SuspendedComponent/>. Це виправляє деякі проблеми з бібліотеками в екосистемі React, хоча ви навряд це помітите.

Докладніше читайте тут.

Потокова передача SSR

На додачу до згаданих вдосконалень до Suspense ми також отримали величезні зміни до архітектури затримки рендерингу на стороні сервера, або Suspense Server-Side-Rendering (SSR).

Ці зміни додають 2 основні можливості — застосування <Suspense> та React.lazy() поряд із візуалізацією HTML-коду потоковою передачею SSR та вибірковим його додаванням, щоб розпочати оновлення застосунку якомога раніше.

Загалом є ще багато новинок, детальніше про них ви можете прочитати на GitHub. Там також є докладний допис про архітектуру Suspense у SSR, тому, якщо ви зацікавлені, це теж варто прочитати!

План дій

Вам, мабуть, цікаво, коли ви зможете користуватися усіма цими новими можливостями.Маємо для вас чудові новини — зараз! Альфа-версія вже доступна на NPM за міткою @alpha і постійно оновлюється. Але вона ще далека від готовності. Ви можете експериментувати з нею, якщо вам цікаво, але пам'ятайте про ймовірність вад та проблем.

До того ж команда React повідомила, що бета-версія з'явиться десь за кілька місяців. Кандидат на реліз (RC) та загальнодоступна версія будуть за кілька тижнів після цього.

Тож найранішою можливою датою випуску буде кінець цього року (2021), а найпізнішою — перша половина 2022 року.

Якщо ж ви не любите постійно переходити на нові версії, то не хвилюйтеся. Оновлення до React 18 повинно пройти гладенько, до того ж перейматися ще рано.

Як випробувати вже

Насамкінець гляньмо, як отримати оновлення до React 18 просто зараз. У робочій групі вже описано як оновити клієнтську і серверну частини.

Встановлення

npm install react@alpha react-dom@alpha

Оновлення клієнтської частини

  • Перейдіть на новий Root API
  • Увімкніть Strict Mode, щоб переглянути додаткові issues (необов'язково)

Оновлення серверної частини

Перейдіть із renderToString (обмежена підтримка Suspense) та renderToNodeStream (застарілий), до pipeToNodeWritable (новий і рекомендований)

Підсумок

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

Без сумніву, паралельний рендеринг є найбільшою зіркою цього свята. Завдяки єдиній зміні в root свого React-застосунку, ви отримуєте більшу гнучкість та поліпшення швидкодії. Додайте ще й нові API, і отримаєте реліз, на який можна очікувати з нетерпінням.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 6.3K
Приєднався: 7 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація