Новые возможности в новом крупном релизе React

Какие новые функции в React 18

React — один из самых, если не самый популярный фреймворк для создания красивых пользовательских интерфейсов и написания более масштабируемого, чистого и понятного кода. В его новой версии React 18, которая является основной версией, появилось несколько новых функций, которые упрощают жизнь разработчика и делают работу пользователя более удобной. Итак, что это за новые функции? Дадим их характеристику.

Параллельная реакция

Звучит как-то странно, но это проще, чем может подумать человек, и улучшить не только работу разработки, но и скорость и пользовательский опыт. Это точка останова в React, потому что она изменяет способ отображения пользовательского интерфейса React по сравнению с предыдущими версиями. В результате пользователи могут быстрее взаимодействовать со страницей, обеспечивая более плавную работу даже на странице с большим объемом данных. И, конечно же, это основа новых функций и хуков, выпущенных в основной версии 18.

Но ждать. Что такое параллелизм? Из документов React:

Параллелизм сам по себе не является функцией. Это новый закулисный механизм, который позволяет React одновременно подготавливать несколько версий вашего пользовательского интерфейса. Вы можете думать о параллелизме как о детали реализации — он ценен из-за функций, которые он открывает. React использует сложные методы в своей внутренней реализации, такие как приоритетные очереди и множественная буферизация. Но вы не увидите эти концепции нигде в наших общедоступных API.

Что это значит? Рендеринг в предыдущей версии React не может быть прерван: как только вы вызываете его, React отрисовывает представление, и если есть какие-либо изменения, вам нужно его повторно отрендерить. Теперь, с параллелизмом, вы можете иметь несколько задач за кулисами и решать, какая из них является наиболее срочной, чтобы сделать ее приоритетной. Это не значит, что React выполняет несколько задач одновременно, но теперь он может выбирать между ними. С этой новой реализацией React может начать рендеринг дерева компонентов, приостановить его в середине выполнения для выполнения другой задачи (для рендеринга другого поддерева компонентов), а затем завершить первое выполнение.

Таким образом, все эти вычисления выполняются за кулисами, и React гарантирует, что пользовательский интерфейс будет согласованным и синхронизированным, даже если процесс рендеринга будет прерван.

Ярким примером является использование крючка useState. До нового крупного релиза React мог обновлять только одно состояние за одно выполнение, все они считались срочными. Но теперь, с новым процессом параллелизма и такими API, как startTransition, вы можете помечать обновления состояний как «несрочные», благодаря чему другие более важные операции будут первыми в стеке.

React Suspense ‹component› на стороне клиента

Компонент саспенса не является новой концепцией. Он был представлен в React 16.6, но имел несколько ограничений и его нельзя было использовать для выборки данных. Это изменилось в последнем основном выпуске, и теперь мы можем использовать компонент «Приостановка» для выборки данных.

Что тогда делает компонент ‹Suspense›? Это упрощает процесс асинхронной выборки данных и отображение загрузки. Теперь его можно обернуть вокруг компонента, который обрабатывает выборку данных, что позволяет разработчикам отображать компонент загрузчика, закодированный декларативным образом, в своем макете.

Вот пример того, как это было обработано раньше:

import React, { useState, useEffect } from "react";
import axios from "axios";
import ListUsers from "./ListUsers";


const AsyncComponent = () => {


 const [loading, setLoading] = useState(true);
 const [data, setData] = useState(null);


 useEffect(() => {
   const fetchData = async () => {
     try {
       const response = await axios.get(
         "https://642d55ab66a20ec9ce9a9e41.mockapi.io/users"
       );
       setData(response.data);
       setLoading(false);
     } catch (e) {
       setLoading(false);
       setData([]);
     }
   };
   fetchData();
 });
 return (
   <>
     {loading ? (
       <p>Loading ...</p>
     ) : (
       <ListUsers list={data} />
     )}
   </>
 );
};
export default AsyncComponent;

Тогда наше приложение будет выглядеть следующим образом:

import React from "react";
import "./App.css";
import AsyncComponent from "./components/AsyncComponent";


function App() {
 return (
   <div className="App">
     <h1>List of Users</h1>
     <AsyncComponent />
   </div>
 );
}
export default App;

Это изменилось с новой версией React. Во-первых, мы собираемся проверить, как выглядит наше приложение React с компонентом «Suspense»:

mport React, { Suspense } from "react";
import "./App.css";
import AsyncSuspendableComponent from "./components/AsyncSuspendableComponent";


function App() {
 return (
   <div className="App">
     <h1>Suspense Example: Full List of Users</h1>
     <Suspense fallback={<p>Loading, please wait...</p>}>
       <AsyncSuspendableComponent />
     </Suspense>
   </div>
 );
}
export default App;

Логика загрузки была абстрагирована от компонента Async. Мы делаем логику загрузки независимой от компонента выборки данных. Это означает, что мы можем изменить способ управления нашими последовательностями загрузки, не изменяя каждый из компонентов, поведение которых зависит от выборки данных. Кроме того, мы можем вкладывать компоненты ‹Suspense› друг в друга, что дает нам возможность показывать загрузчик для всего раздела или его дочерних компонентов. Конечно, у нас есть компонент, который стал намного чище и проще в обслуживании.

import React from "react";
import ListUsers from "./ListUsers";
import { fetchData } from "../lib/suspense-demo-api";
const resource = fetchData();


const AsyncSuspendableComponent = () => {
 const data = resource.data.read();
 return <ListUsers list={data} />;
};
export default AsyncSuspendableComponent;

Обратите внимание, что команда React не рекомендует внедрять компонент ‹Suspense› самостоятельно, так как это «специальная» реализация. Наоборот, предлагается использовать фреймворки, которые уже интегрировали логику выборки данных с Suspense, такие как Next.js, Gatbsy, Relay и Apollo.

Задержка на сервере

Не только на стороне клиента, но и на сервере функция приостановки в React 18 представляет:

  1. Разделение кода на сервере.
  2. Потоковая отрисовка на сервере.

Клиентский рендеринг и серверный рендеринг

Когда у вас есть клиентское приложение, вам нужно загрузить все ресурсы, чтобы сделать его интерактивным и удобным для пользователя. Однако, если ваш пакет javascript огромен или ваше соединение медленное, пользователю может потребоваться много времени, чтобы взаимодействовать с Интернетом или просматривать соответствующий контент.

Для оптимизации этого мы можем использовать серверный рендеринг: мы загружаем первый подход HTML на сервер и отправляем его клиенту, тем временем сервер ждет получения данных или подготовки необходимых ресурсов JavaScript, но пока это не произойдет вы даете пользователю некоторую информацию и подготавливаете представление для «увлажнения» его информацией, которую ожидает сервер.

В чем проблема с этим? Это кажется очень полезным методом, но ограничение серверного рендеринга, как это было в React 17 или более ранних версиях, заключается в том, что вы рендерите все или ничего, и, возможно, какая-то часть вашего приложения занимает так много времени, чтобы получить данные, тогда вы не сможете гидратировать всю сеть. Именно тогда на сервере появляется компонент Suspense‹company›.

С помощью приостановки вы можете обернуть медленную часть вашего приложения внутри компонента приостановки и отложить загрузку этого компонента, но не всего приложения. Это означает, что в React 18 медленный компонент может идти со всеми HTML-заполнителями, отправленными с сервера, и ждать, пока его увлажнят, независимо от других компонентов.

Все это происходит до того, как какой-либо JS или React загрузит страницу, что значительно улучшает взаимодействие с пользователем и воспринимаемую пользователем задержку.

Автоматическое дозирование

Эта новая функция от React заставляет приложение повторно отображать различные состояния группировки компонентов, обновляя их, и выполнять их всего за один рендеринг. Раньше React выполнял повторный рендеринг для каждого обновления состояния. Теперь этого можно избежать, так как экран не «мигает» перед пользователем.

До этого изменения это обновление состояния не выполнялось в группе, за исключением некоторых обработчиков событий, таких как обещания или onClickсобытия, для которых его обратный вызов изменяет несколько состояний при вызове, как показано ниже:

const handleOnClick=>{
  setSomeState();
  setAnotherState();
  setThirdState(); 
}

/* Before react 18, when setting states in events handlers, we can "batch"
events and allow just one render. */

Государственный переход

Это новая концепция в React. Это позволяет расставлять приоритеты между обновлениями состояния в двух сценариях: срочном и несрочном. Что это значит?

Например, у нас есть поисковый ввод, который отображает результаты в заданном блоке. Срочное обновление — это обновление состояния ввода, которое должно быть срочным, поскольку пользователю необходимо немедленно увидеть изменения. Это не ваш случай отображения результатов, потому что пользователь знает, что потребуется время, чтобы получить то, что он ищет.

Эти несрочные обновления называются переходами. Отмечая несрочные обновления пользовательского интерфейса как «переходы», React будет знать, каким обновлениям отдавать приоритет. Это упрощает оптимизацию рендеринга и избавление от устаревшего рендеринга.

До этой функции для достижения такого эффекта разработчик использовал такие методы, как устранение дребезга. Теперь, с этим новым API, реализовать такое поведение стало проще.

import { startTransition } from 'react';

// Urgent: Show what was typed
setInputValue(input);

// Mark any non-urgent state updates inside as transitions
startTransition(() => {
  // Transition: Show the results
  setSearchQuery(input);
});

но чем отличаются переходы от устранения дребезга или setTimeOut?

  1. startTransition выполняется немедленно, в отличие от setTimeout.
  2. setTimeout имеет гарантированную задержку, тогда как задержка startTransition зависит от скорости устройства и других срочных рендеров.
  3. Обновления startTransition могут быть прерваны, в отличие от setTimeout, и не заморозят страницу.
  4. React может отслеживать состояние ожидания, если оно помечено с помощью startTransition.

Строгий режим

Строгий режим в React 18 имитирует монтирование, размонтирование и повторное монтирование компонента с предыдущим состоянием. Это закладывает основу для многократного использования состояния в будущем, когда React может немедленно монтировать предыдущий экран, повторно монтируя деревья, используя то же состояние компонента перед размонтированием.

Строгий режим гарантирует устойчивость компонентов к многократному монтированию и размонтированию эффектов.

Краткое содержание

Итак, мы рассказали некоторые подробности о следующих новых функциях, появившихся в React 18:

  1. Параллелизм.
  2. саспенс
  3. Автоматическое дозирование
  4. Переходы
  5. Строгий режим

Обновить текущую версию React до версии 18 несложно, так что давайте попробуем. Эти новые функции дадут нам основу для новых изменений, которые появятся в будущих выпусках, изменений, которые улучшат не только пользователей, но и разработчиков.