Поиск по сайту:

Как перейти на React 18


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

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

Установка Реакт 18

Прежде чем делать что-либо еще, используйте npm для обновления зависимости React вашего проекта до версии 18:

$ npm install react@latest react-dom@latest

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

$ npm start

Включение функций React 18: новый корневой API

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

ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17.

Это сообщение об устаревании можно смело игнорировать, если вы не готовы обновить свой проект. Если вы хотите использовать возможности React 18, вам необходимо внести описанное в нем изменение. Старая функция ReactDOM.render() была заменена новым корневым API, более объектно-ориентированным. Помимо улучшенной простоты использования, он также активирует систему параллельного рендеринга, которая поддерживает все новые функции заголовков.

В файле index.js или app.js найдите строки, похожие на эти:

import App from "./App.js";
import ReactDOM from "react-dom";
 
const container = document.getElementById("react");
ReactDOM.render(<App />, container);

Это типичная точка входа для приложения React. Он отображает экземпляр импортированного компонента App в качестве корневого элемента вашего приложения. Визуализированный контент сохраняется как innerHTML элемента HTML с id=\react\.

Чтобы переключиться на корневой API React 18, замените приведенный выше код следующим:

import App from "./App.js";
import {createRoot} from "react-dom/client";
 
const container = document.getElementById("react");
const root = createRoot(container);
root.render(<App />);

Эффект аналогичен старому API ReactDOM.render(). Вместо инициализации корневого элемента и рендеринга вашего приложения как одной императивной операции React 18 заставляет вас сначала создать корневой объект, а затем явно отображать ваш контент.

Затем найдите места в коде, где вы размонтируете корневой узел. Измените ReactDOM.unmountComponentAtNode() на новый метод unmount() для вашего корневого объекта:

// Before
import App from "./App.js";
import ReactDOM from "react-dom";
 
const container = document.getElementById("react");
ReactDOM.render(<App />, container);
ReactDOM.unmountComponentAtNode(container);
 
// After
import App from "./App.js";
import {createRoot} from "react-dom/client";
 
const container = document.getElementById("react");
const root = createRoot(container);
root.render(<App />);
root.unmount();

Замена обратных вызовов рендеринга

Необязательный аргумент обратного вызова метода ReactDOM.render() не имеет прямого аналога в корневом API React 18. Ранее вы могли использовать этот код для регистрации Rendered! в консоли после того, как React завершит рендеринг корневого узла:

import App from "./App.js";
import ReactDOM from "react-dom";
 
const container = document.getElementById("react");
ReactDOM.render(<App />, container, () => console.log("Rendered!"));

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

import {createRoot} from "react-dom/client";
 
const App = ({callback}) => (
    <div ref={callback}>
        <h1>Demo App</h1>
    </div>
);
 
const container = document.getElementById("react");
const root = createRoot(container);
root.render(<App callback={() => console.log("Rendered!")} />);

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

Отладка проблем обновления

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

Проверьте <строгий режим>

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

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

Поддержка пакетного обновления состояния

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

const Component = () => {
 
    const [query, setQuery] = useState("");
    const [queryCount, setQueryCount] = useState(0);
 
    /**
     * Two state updates, only one re-render
     */
    setQuery("demo");
    setQueryCount(queryCount + 1);
 
};

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

const Component = () => {
 
    const [query, setQuery] = useState("");
    const [queryId, setQueryId] = useState("");
    const [queryCount, setQueryCount] = useState(0);
 
    const handleSearch = query => {
       fetch(query).then(() => {
 
            setQuery("demo");
            setQueryCount(1);
 
            // In React 17, sets to "query-1"
            // In React 18, sets to "query-0" - previous state update is batched with this one
            setQueryId(`query-${queryCount}`);
 
        });
    }
 
};

Вы можете отключить это поведение в ситуациях, когда вы не готовы рефакторить свой код. Оберните обновления состояния в flushSync(), чтобы принудительно выполнить их немедленную фиксацию:

const Component = () => {
 
    const [query, setQuery] = useState("");
    const [queryId, setQueryId] = useState("");
    const [queryCount, setQueryCount] = useState(0);
 
    const handleSearch = query => {
       fetch(query).then(() => {
 
            flushSync(() => {
                setQuery("demo");
                setQueryCount(1);
            });
 
            // Sets to "query-1"
            setQueryId(`query-${queryCount}`);
 
        });
    }
 
};

Прекратите использовать удаленные и неподдерживаемые функции

После того, как все вышеперечисленные аспекты будут учтены, ваше приложение должно быть полностью совместимо с React 18. Хотя есть еще несколько изменений поверхности API, они не должны повлиять на большинство приложений. Вот некоторые из них, о которых следует знать:

  • unstable_changedBits был удален — этот неподдерживаемый API позволял отказаться от контекстных обновлений. Он больше не доступен.
  • Полифилл Object.assign() был удален. Вам следует вручную добавить пакет полифилла object-assign, если вам нужна поддержка очень старые браузеры без встроенной функции Object.assign().
  • Internet Explorer больше не поддерживается. React официально прекратил совместимость с Internet Explorer до прекращения поддержки браузера в июне. Вам не следует обновляться до React 18, если вам по-прежнему требуется, чтобы ваше приложение работало в IE.
  • Использование приостановки с откатом undefined теперь эквивалентно null — границы приостановки с fallback={undefined} были ранее пропущены, что позволяет каскадировать код до следующей родительской границы в дереве. React 18 теперь учитывает компоненты приостановки без отступления.

Рендеринг на стороне сервера

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

В соответствии с новым корневым API вы должны заменить старую функцию hydra() в коде на стороне клиента новой hydraRoot(), предоставленной react- пакет dom/client:

// Before
import App from "./App.js";
import ReactDOM from "react-dom";
 
const container = document.getElementById("react");
ReactDOM.hydrate(<App />, container);
 
// After
import App from "./App.js";
import {createRoot} from "react-dom/client";
 
const container = document.getElementById("react");
const root = hydrateRoot(container, <App />);

В коде на стороне сервера замените устаревшие вызовы API рендеринга их новыми аналогами. В большинстве случаев следует заменить renderToNodeStream() на новый renderToReadableStream(). Новые потоковые API открывают доступ к возможностям рендеринга потокового сервера React 18, где сервер может продолжать доставлять новый HTML в браузер после первоначального рендеринга вашего приложения.

Начните использовать функции React 18

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

Некоторые из добавленных функций включают в себя основные обновления Suspense, способ определения приоритета обновлений состояния с помощью Transitions и встроенный механизм для ограничения повторных рендеров, вызванных несрочными, но частыми обновлениями. Также есть несколько различных изменений и улучшений: вы можете вернуть undefined из метода компонента render(), предупреждение о вызове setState() в размонтированные компоненты были удалены, а несколько новых атрибутов HTML, таких как imageSizes, imageSrcSet и aria-description, распознаются средством визуализации React DOM.

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

React 18 стабилен и готов к использованию. В большинстве случаев процесс обновления должен быть быстрым и простым, требуя только обновления npm и переключения на новый корневой API. Тем не менее, вы все равно должны протестировать все свои компоненты: они могут вести себя по-разному в некоторых ситуациях, например, в строгом режиме или при применении автоматической пакетной обработки.

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




Все права защищены. © Linux-Console.net • 2019-2024