СонарКуб интерфейс написан на Реагировать и недавно мы прошли процесс обновления с версии 17 до 18. Чтобы дать вам более полное представление, приложение также написано на Машинопись и использует Является с Библиотека тестирования React (RTL) для тестирования.
Мы хотели поделиться тремя наиболее важными проблемами, с которыми мы столкнулись, и уроками, которые мы извлекли в ходе обновления. Вкратце, это были:
- Некоторые типы TypeScript изменены.
- Библиотеку тестирования React также необходимо обновить.
- React 18 приносит кардинальные изменения
Давайте разберемся, что это значит и как мы с ними справились.
Примечание. Этот пост был написан в соавторстве с командой разработчиков интерфейса SonarQube в составе Дэвида Чо-Лера, Амбруаза Кристеа и Филиппа Перрена.
Изменения типа TypeScript
Руководство по обновлению React 18 указывает на то, что оба @types/react
и @types/react-dom
необходимо обновлять по мере обновления, и «наиболее заметным изменением является то, что children
prop теперь необходимо указывать явно при определении реквизита».
Хорошая новость для этого обновления заключается в том, что Себастьян Зильберманниз основной команды React, поддерживает коллекция кодмодов которые помогают автоматически обновлять типы при обновлении с React 17.
Вы можете запустить codemod с помощью npx следующим образом:
Он представит ряд преобразований, которые вы можете применить, и по умолчанию будет использовать те преобразования, которые необходимы.
Например, преобразование для вывода списка children
prop явно примет компонент, который выглядит следующим образом:
и замените его на:
Однако будьте осторожны: мы обнаружили, что codemod может вкладывать PropsWithChildren
type, и ваш тип может выглядеть так:
Хотя это и не вредно, вам придется исправлять эти типы по мере их обнаружения.
Новые типы также более разборчивы в некоторых областях. Например, ранее мы могли переопределить тип children
в таком интерфейсе:
С типами React 18 это больше не работает, и теперь вы должны опустить объявление children
первый.
Новые типы также не допускают неявного any
типы параметров для useCallback
функция. Вам нужно будет явно объявить типы, например:
Когда вы обновляетесь @types/react
до версии 18, ожидайте увидеть несколько подобных проблем.
Обновление библиотеки тестирования React
Мы обнаружили, что многие из наших тестов, которые раньше проходили успешно, теперь не удались после обновления React и RTL. Было две категории неудач: выбор времени и призывы к act()
.
Поддельные таймеры
РТЛ использует setTimeout
на определенную задержку при моделировании пользовательских событий, но это не очень хорошо сочетается с Поддельные таймеры Jest. Это приводило к зависанию тестов и сбою с тайм-аутом.
В версии 14.1.0 в RTL добавлен advanceTimers
вариант к шагу настройки для пользовательское событие так что вы можете предоставить свой собственный таймер. Нам удалось исправить наши тесты, пройдя jest.advanceTimersByTime
метод.
Отыгрывание
боялся act(...)
предупреждение какое-то время мешал нашей кодовой базе, и в некоторых случаях его исправляли добавлением дополнительного вызова act
вокруг некоторых событий и помощников RTL.
Помощники RTL используют act
внутри компании, поэтому при добавлении дополнительного вызова в act
изначально было допустимым обходным путем для подавления предупреждения, теперь оно приводило к сбою тестов. Удаление лишних звонков на act
снова сдала анализы. Если вы по-прежнему получаете предупреждения, у Кента С. Доддса есть подробная статья на эту тему. что вызывает предупреждение act(…) и как его исправить в контексте РТЛ.
Реагируйте на 18 критических изменений
Самое большое изменение в React 18 находится в корне приложения. ReactDOM.render
больше не поддерживается и его следует заменить на createRoot
. Хотя на первый взгляд это кажется простым изменением, которое обеспечивает лучший способ управления корнем приложения React, на самом деле оно меняет то, как React визуализирует ваше приложение. Включены две новые функции: автоматическая пакетная обработка и новый параллельный рендеринг.
Параллельный рендеринг позволяет React прервать рендеринг компонента, если есть другая работа, которую необходимо выполнить с более высоким приоритетом. Вы соглашаетесь на такое поведение, определяя обновление состояния как переход с помощью useTransition
крюк. Если вы не дадите свое согласие, ваши компоненты будут отображаться последовательно, как и раньше, поэтому при обновлении приложения это не должно иметь никакого значения.
Однако автоматическое пакетирование включается немедленно. Автоматическая пакетная обработка — это улучшение производительности в React 18, позволяющее сократить количество рендерингов за счет сбора изменений состояния в одно обновление. Однако это может вызвать неожиданное поведение.
Мы обнаружили, что некоторые части нашего кода не подходят для этой новой пакетной обработки, когда несколько тестов начали давать сбой. Тесты ожидали рендеринга частей компонентов, но обнаружили, что они пусты.
Мы поняли, что эта пакетная обработка включает в себя любой подконтекст выполнения в одной области! Это означает, что если у вас есть setState
затем Promise, который также выполняет setState
когда он разрешается/отклоняется, оба изменения состояния будут группироваться в конце области, если они происходят близко друг к другу (например, в тестах, где имитируемые запросы выполняются почти мгновенно).
В этом упрощенном примере двух методов в компоненте на основе классов мы устанавливаем состояние, затем в теле асинхронной функции мы опираемся на это новое состояние в условном выражении.
В React 17, когда handleFetchProjectsClick
назывался, он устанавливал shouldFetch
государство, чтобы true
тогда позвоните fetchProjects
. В пределах fetchProjects
тест на shouldFetch
было бы true
и данные были получены. Это связано с тем, что задача обновления состояния выполняется до fetchProjects
обещание обрабатывается.
В React 18 с createRoot
проекты не загружаются, поскольку обновление состояния отложено до конца handleFetchProjectsClick
так когда fetchProjects
бежит shouldFetch
все равно будет ложным.
Если вам нужно гарантировать выполнение кода после установки состояния, вы можете использовать форму обратного вызова setState или новый метод ReactDOM.flushSync()
метод.
Асинхронный рендеринг в тестах
Вышеупомянутое исправило рендеринг компонентов на странице, но мы обнаружили, что тесты по-прежнему терпят неудачу. Поэтапная отладка этих ошибок показала, что при первоначальном рендеринге содержимого не было, но когда мы повторно отрендерили компонент, оно появилось. Поскольку теперь мы использовали setState
обратного вызова для получения данных, первоначальный рендеринг не включал содержимое.
Наши тесты использовали синхронные методы RTL для поиска этого контента на странице, например:
Замена RTL синхронный getBy
запросы с асинхронным await findBy
запрос исправляет проблему. Например:
Используя findBy
запрос использует waitFor
под капотом, чтобы дать DOM время для обновления, если это не происходит немедленно.
Обновление прошло успешно
Пользовательский интерфейс SonarQube теперь успешно работает на React 18. Хотя некоторые проблемы, с которыми мы столкнулись, были связаны с необходимостью обновления набора тестов, другие были обнаружены, потому что у нас есть комплексный набор тестов как для модульных тестов для компонентов, так и для комплексных тестов. -завершить тестирование, чтобы избежать сбоев в работе, когда пришло время развертывания. Написание тестируемого кода — это часть написания адаптируемого кода, одно из свойств чистого кода.. Эти тесты выявили моменты, которые необходимо обновить, и дали нам уверенность в том, что, когда они пройдут, приложение будет готово.
Если вы используете React 17 и планируете обновление, надеемся, что этот опыт поможет вам преодолеть некоторые ловушки.
2024-01-26 13:07:43
1706408389
#Уроки #извлеченные #при #обновлении #до #React #SonarQube