Очередная статья про React Context и объяснение того, как с ним работать верно для обработки состояния. Статья поясняет, что разработчики предпочитают стейт-менеджеры, например Redux или Zustand вместо того, чтобы разобраться с контекстами.
В базовом примере автор статьи использует контекст для передачи state и setState через контекст без каких либо мемоизаций, и уже в таком сценарии Реакт не делает лишние рендеры компонентов, которые не были затронуты изменением состояния:
Использование такого контекста позволяет проверить корректность его работы – лишних рендеров не будет. Для примере можно собрать такую же структуру как и в статье:
Для такого примера App и UncontrolledComponent не будут рендерится, т.к. не используют Context Consumer.
Автор считает, что путаница возникает из-за того, что в один контекст складывают все возможные состояния.
Совет по оптимизации
Если передавать дочерние элементы через пропы, например через {children}, то они не будут рендерится при изменении состояния компонента. Данный подход хорошо себя показывает вкупе с React.Context.
Всё это полезно для небольших и средних приложений, а для крупных уже лучше использовать стейт-менеджеры – их проще поддерживать и писать, и в большом приложении мы уже готовы заплатить весом бандла за улучшение DX.
В мире разработки на React’е мы очень часто пишем компоненты, которые тесно связаны, но потом обнаруживаем, что такие компоненты тяжело тестировать, поддерживать и изменять.
Статья предлагает рассматривать инверсию зависимостей, чтобы избавиться от таких проблем, как:
тесная связь кода с API-слоём;
сложность тестирования вызовов API;
трудности в изменении источника данных;
сложности с пониманием состояния запросов и т.д.
Для использования принципа инверсии зависимостей необходимо убедится в том, что модули разного уровня должны зависеть от интерфейсов, а не конкретных реализаций:
Классы, которые имплементируют интерфейс для работы с API-слоём очень легко использовать, тестировать, поддерживать и изменять, т.к. компоненты будут принимать в пропах экземпляры таких интерфейсов.
Если придерживаться функционального подхода, то можно создать хуки, которые внутри себя уже должны работать с интерфейсами абстракций, что реализовать на практике намного сложнее, чем классовый подход.
Из статьи можно вынести лучшие практики:
необходимо определять четкие интерфейсы, представляющие зависимости в проекте;
использовать экземпляры интерфейсов через пропы или контекст (или через тот самый DI – TSyringe);
писать легко тестируемые компоненты с изолированными тестами.
Уже некоторая традиция – каждые несколько недель анонсировать новый бандлер. На этот раз новый бандлер – Rslib, разрабатываемый для экосистемы Rstack.
Главными фичами бандлера явлются поддержка экосистемы – легко заменить один бандлер на другой, поддержка вывода нескольких форматах, Bundle & Bundleless режимы и работа с различными ресурсами.
Отдельно Rslib отмечает хорошую работу с Module Federation с использование более гибкого варианта, чем в Wepback. Скорее всего Rslib использует Module Federation 2.0, добавляющий работу с типизацией, распределением зависимостей, поддержкой Manifest’ов и режиме в рантайме.
С каждым новым бандлером мы должны выбирать приоритетные фичи: лучше сборка и вес бандла, более лучшая поддержка TypeScript, или распределение на микрофронтеды.
В бету Хромиума 137 добавили несколько крутых фич для CSS, и первая из них – if() в CSS! Функция if() – лёгкий способ на основе CSS-переменных описывать условные значения для свойств. Например можно простым способом описать переключение светлой и тёмной темы только через одну переменную:
Функция if() на данный момент – сокращение синтаксиса для кастомных CSS-функций.
Вторая крутая фича – логические свойства для изменения порядка в a11y-дереве. Это полезно для тех случаев, когда порядок элементов изменен через order во Флексах, или через grid-area в Гридах. До 137 Хромиума доступность таких элементов страдала, т.к. порядок визуально был один, а через скринридеры – другой. Теперь мы сможем ещё лучше настраивать Accessibility.
Из приятных плюшек нам добавят более лучшую поддержку функции shape(), добавленной в Chrome 136, которая позволяет описать кастомный путь для обрезки контента, а со 137 версии эта функция станет доступна и для настройки отступов.
Safari Technology Preview выкатил новую фичу – CSS-функцию contrast-color(), которая на основе переданного цвета возвращает либо черный, либо белый цвет. Данная функция может быть очень полезно для разработки специальных режимов отображения сайтов и её можно использовать в специальном медиа-запросе, который узнаёт, что пользователь предпочитает более контрастный интерфейс.
.button { --color: royalblue; --bg-color: rgb(from var(--color) r g b / 20%); color: var(--color); background-color: var(--bg-color); @media (prefers-contrast: more) { color: contrast-color(var(--color)); }}
Расчёт контрастного цвета
Контрастный цвет рассчитывается согласно спецификации WCAG 2.01, и в будущем ожидается, что в WCAG 3.0 будет добавлен улучшенный алгоритм расчёта контрастности цвета – Accessible Perceptual Contrast Algorithm (APCA).
В 2021 году в Safari Technology Preview 122 была добавлена более гибкая функция для работы с контрастными цветами, которая позволяла сравнить два цвета между собой и выбрать один из переданных цветов. Фича в итоге не была добавлена в браузеры, и её перенесли в CSS Color Module Level 6 и переименовали в contrast-color(). В будущем спецификация подразумевает, что мы сможем узнать контраст цвета с использованием определенного алгоритма и выбрать один из переданных цветов.
В стандарте ECMAScript появится явное управление ресурсами – более явный подход для работы с дескрипторами файлов, соединениями и любыми объектами, реализующими [Symbol.dispose]() или [Symbol.asyncDispose](). Для удобства работы с такими ресурсами появятся новые ключевые слова – using и await using, которые были добавлены в TypeScript 5.2.
Ключевое слово using вызывает [Symbol.dispose]() синхронно при выходе из блока, для await using схожая логика, за тем отличием, что в [Symbol.asyncDispose]() можно написать асихнронную логику.
Дополнительно к ключевым словам и специальным символам были добавлены новые классы – DisposableStack и AsyncDisposableStack, которые необходимы для агрегации ресурсов. Классы для агрегации обеспечивают более широкий функционал и позволяют описать поведение для не-disposable ресурсов, добавить обработку в конце всех dispose и явно вызвать очистку ресурсов.
Новую фичу обсуждали на прошедшем meeting of Ecma TC39 и её перевод в Stage 4, а ещё она стала доступна с Хромиума 134.