Главная Категории Контакты Поиск

Что нового в React 16.9

Узнай об обновлениях React v16.9.

React ·29.08.2019·читать 10 мин 🤓·Автор: Alex Myzgin

Депрекация

Давай начнем с деприкациях, устаревших частях кода, которые были включены в React v16.9; они помогут нам лучше подготовиться к v17 (и другим будущим версиям) в будущем.

Нет больше JavaScript: URL

URL-адреса, начинающиеся с javascript: долгое время считались опасными из-за потенциальной возможности попадания вредоносных данных в приложение:

const userProfile = {
  websiteUrl: "javascript: alert('you got hacked')";
}

<a href={userProfile.websiteUrl}>Мой веб-сайт</a>

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

Как уже упоминалось, этот функционал устарел в v16.9 и показывает только предупреждение. Можно использовать dangerouslySetInnerHTML, но всё равно могут возникнуть проблемы.

В будущей основной версии (не обязательно v17) этот функционал будет вызывать ошибку. Лучше всего прекратить его использовать совсем, чтобы избежать неприятностей в будущем.

factory компонентов больше нет

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

function FactoryComponent() {
  return {
    render() {
      return <div />;
    }
  };
}

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

React команда упомянула, что factory компонент используется редко и, вероятно, не повлияет на большинство современных кодовых баз.

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

Небезопасные методы жизненного цикла переименованы

Более года назад команда разработчиков подумала, что методы жизненного цикла, которые считались небезопасными, будут переименованы в будущем выпуске 16.x, а старые имена полностью удалены в версии 17.x.

Например:

  • componentWillMount переименован в UNSAFE_componentWillMount;
  • componentWillReceiveProps переименован в UNSAFE_componentWillReceiveProps;
  • componentWillUpdate переименован в UNSAFE_componentWillUpdate;

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

Цель UNSAFE_ наименования состоит в том, чтобы облегчить нам, разработчикам, идентификацию потенциально проблемного кода при выполнении проверок и тому подобного.

Чтобы упростить миграцию, существует сценарий «codemod», который может обновить весь проект до нового соглашения об именах UNSAFE_:

npx react-codemod rename-unsafe-lifecycles

Новый функционал

Этот выпуск React немного освещает новые функции.

Измерение производительности с <React.Profiler>

React Profiler был впервые добавлен в React DevTools в версии 16.5. Эта функция измеряет каждый отрисованный компонент, тем самым определяет «затраты» рендеринга и уязвимые места производительности в приложении React.

Чтобы использовать его, можем открыть DevTools в React, запустить запись, визуализировать некоторые компоненты React, а затем остановить запись.

Profiler полезный, но немного громоздкий. Нужно начать запись и остановить её, а затем проверить части записи, которые имеют большое время загрузки. Вот почему у нас теперь есть компонент <React.Profiler>, который можно использовать для сбора метрик производительности программным способом.

Для нового компонента требуется свойство id, а также свойство onRender, которое будет запускаться каждый раз при обновлении компонента в дереве и запускать повторную визуализацию:

import React, { Profiler } from "react";

render(
  <Profiler id="my-app" onRender={onRender}>
    <App>
      <Switch>
        <Route {...props} />
        <Route {...props} />
      </Switch>
    </App>
  </Profiler>
);

Обратный вызов onRender будет получать информацию о том, какой компонент был повторно обработан, сколько времени это заняло и другую ценную информацию. Более подробно о profiler здесь.

Кроме того, profiler автоматически отключается в production среде, поэтому нет никакой дополнительной логики для реализации его отключения.

Асинхронный ReactTestUtils.act()

В React v16.8 появилась утилита act(), которая помогает разработчикам создавать тесты пользовательского интерфейса. При написании тестов пользовательского интерфейса существуют такие задачи как рендеринг, события взаимодействия с пользователем такие как щелчок или выборка данных, которые можно считать «единицами» взаимодействия с приложением React.

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

React предоставляет вспомогательный метод act(), который гарантирует, что все обновления, связанные с этими «модулями», были обработаны и применены к DOM прежде, чем он сделает какие-либо утверждения.

Хоть утилита act() и была чрезвычайно полезной, она была синхронной, и не было простого способа заставить её работать более асинхронно. Это могло привести к некоторым единичным предупреждениям в логах.

К счастью, команда React улучшила утилиту act() в React v16.9, чтобы та могла работать асинхронно!

await act(async () => {
  // ...
});

Исправление ошибок

Релиз React никогда не завершается без каких-либо заметных исправлений ошибок:

  • Исправлена утечка памяти, вызванная сохранением удаленных поддеревьев;
  • Улучшение обработки бесконечных циклов, вызванных setState внутри useEffect.

Бесконечный цикл, вызванный setState в useEffect, теперь выводит аналогичную ошибку, которую видим, когда вызываем setState в componentDidUpdate в компоненте класса. Вот пример кода:

function App() {
  const [counter, setCounter] = React.useState(0);
  React.useEffect(() => {
    setCounter(counter + 1);
  });
  return <h1>Watch out infinite loop in the console!</h1>;
}
  • Исправлен сбой в <Suspense> при вызове findDOMNode().

Компонент <React.Suspense> используется для отложенной загрузки компонентов, которые не нужны при первоначальной визуализации. Но, начиная с версии 16.7, многие разработчики начали получать сообщения об ошибке Invariant Violation: Unable to find node on an unmounted component.

После проверки, разработчики выяснили, что ошибка вызвана вызовом ReactDOM.findDOMNode() внутри Suspense. В этом выпуске сбой исправлен.

Установка React v16.9

React v16.9 готов для установки; всё что нужно сделать - это установить его через любимый менеджер пакетов:

# Через npm
npm install --save react@^16.9.0 react-dom@^16.9.0

# Через yarn
yarn add react@^16.9.0 react-dom@^16.9.0

Источники

https://reactjs.org/blog/2019/08/08/react-v16.9.0.html

https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html

https://github.com/reactjs/react-codemod

Website, name & logo
Copyright © 2019. Alex Myzgin