Доклад с SPb IT Club Meetup №3
Фреймворк, который нельзя называть

ReactJS *
JavaScript-библиотека для создания интерфейсов
Исследовал интернет и наткнулся на GitHub Unwrapped. Он на основе активности в GitHub создаёт видео, где можно увидеть часто используемые языки, часы спонтанной работы, звёзды и всё остальное. Достаточно ввести только имя профиля, чтобы получить видео. Код открыт.
Сделано с использованием Remotion — тоже с открытым кодом, которая позволяет автоматизировать создание видео на React в веб. Документация хорошая, но надо разбираться. Увидел это и решил, что круто, надо поделиться!
P.S. Моя активность в этом ролике, если кому-то будет интересно.
Мы подготовили гайд по настройке автогенерации с помощью Orval. Он облегчит жизнь разработчиков, которым часто не хватает времени на оптимизацию и рефакторинг приложений. Весь процесс описан пошагово, код и ссылки на библиотеки вы также найдете в статье https://habr.com/ru/articles/848182/
Привет друзья! Сделал максимально простые аналоговые часы на SVG. Можно ли их еще упростить или уменьшить? Или добавить немного улучшений без переусложнения? Буду рад вашим идеям!
Вот CodeSandbox

Сделано с помощью библиотеки Fusor
Как в нативе: эти Web API поднимут ваше веб-приложение в стратосферу

Салют, на связи Clevertec. Сейчас наша команда разрабатывает веб-версию банкинга с использованием React. С помощью Web API даем пользователям фичи, которые они привыкли получать в нативных приложениях. Отрываем от сердца список решений 😉
- Web Share API – для обмена ссылками, текстом и файлами с другими приложениями на устройстве. К примеру, удобно отправить чек об оплате в мессенджере, не покидая банковское приложение.
- Contact Picker API позволяет делиться контактами из своего списка. Можно использовать для перевода по номеру телефона. Не нужно вводить цифры вручную – поле автоматически заполнится контактом из телефонной книги.
- Media Capture and Streams API в нашем случае позволяет отсканировать QR-код с помощью камеры устройства. Нажимаешь на “Сканировать QR” – открывается окно с камерой, она считывает код и переводит пользователя в дерево платежей.
- Web OTP API открывает возможность автоматически вставлять код из смс. Например, для подтверждения оплаты на телефон приходит сообщение. Внизу экрана появляется модальное окно с подтверждением вставки. И после нажатия на “Разрешить” код отображается в поле ввода.
Подробнее про этот опыт использования Web API мы рассказали в отдельной статье. Что вы думаете о Web API, какие используете? Расскажите в комментариях, будем взаимно полезны друг другу.
Кнопка со счётчиком: React vs Fusor

Fusor это новый способ разработки вэб приложений https://github.com/fusorjs/dom
Разработчик Мишан Пудель представил открытое локальное приложение в виде клона интерфейса Windows 11 на React.js с некоторыми компонентами ОС, включая работающий браузер Chrome, инструментарий VS Code, игру Emoji Tic-Tac-Toe, клиент Spotify в качестве музыкального проигрывателя и калькулятор.

Используемые в проекте технологии:
React.js: для создания интерактивного пользовательского интерфейса.
Tailwind CSS: для стилизации компонентов и создания дескопного окружения.
React Router DOM: для управления навигацией и маршрутизацией в приложении.
Framer Motion: для добавления анимации и переходов.
React Draggable: для создания элементов, которые можно перетаскивать.
Страница входа в ОС: можно ввести что угодно на странице входа, чтобы получить доступ к приложению. Фактические учётные данные не нужны. Щёлкните по значкам на рабочем столе, чтобы открыть различные приложения. Используйте панель задач для переключения между открытыми приложениями. Взаимодействуйте с приложениями, чтобы изучить их функции и возможности.
Установка проекта локально:
Clone the repository: git clone https://github.com/MishanPoudel/Windows11-3.0;
Navigate to the project directory: cd Windows11-3.0;
Install the dependencies: npm install;
Start the development server: npm start;
Открыть в браузере: http://localhost:3000.
Два основных подхода к разработке UI-китов
1. All-in подход. Подключение компонента вместе со стилями или без них. Здесь любой компонент — это самостоятельная единица, которая уже содержит всё нужное. Внутри этого подхода можно выделить два подвида:
Инлайн-стили через Styled Components (возможно, добавить просто подключение стилей внутри компонента). Этот метод позволяет писать стили непосредственно в компоненте. При этом стили изолированы, что уменьшает возможность конфликтов между стилями разных компонентов.
Без добавления стилей (Headless). В этом случае компоненты предоставляют только логику без UI, что позволяет самостоятельно управлять стилями. Для создания подобной библиотеки нужно также ознакомиться с паттерном Compound component.
2. Dependency CSS & Bundle CSS подход. Второй большой подход — когда стили и компонент подключаются по отдельности. В этом случае стили и логика компонента отделены друг от друга.
Dependency CSS: этот способ подключения улучшает модульность и позволяет загружать стили только тогда, когда они действительно необходимы.
Bundle CSS предполагает подключение всех стилей сразу и отдельно — компонента. По сути, в этом случае все стили объединены в общий бандл и импортируются в корне проекта.
Но при написании они схожи, и стили к компоненту подключаются как модули.

О том, как создавать и подключать UI-киты, рассказываем в нашем гайде для начинающих Frontend-разработчиков. Там вы найдете примеры кода и полезные ссылки.
Вышел React 19 beta.
Команда react.js во всю готовится к предстоящей конференции и видимо, несмотря на большие сомнения, именно на ней они представят React 19. На сайте уже была опубликована страница релиза.
В релизе всё то, о чём рассказывала команда next.js - action для формы, новые хуки, серверные компоненты и серверные действия, метаданные страницы и предзагрузка ресурсов из коробки. Из нового (или упущенного мной) - для передачи ref больше не нужно использовать forwardRef, обновлённое API контекстов и продвинутая поддержка таблиц стилей.
Вместе с релизом был опубликован и гайд на обновление до 19 версии для библиотек. В гайде можно отметить значительные удаления функционала помеченного в последние годы как устаревший.
Также вчера вышел React 18.3.0, а уже сегодня вышла минорка - React 18.3.1. Это промежуточные релизы, в которых добавили предупреждения о том, что будет помечено как устаревшее или удалено. Так можно подготовить проекты к предстоящему обновлению.
Препарируем React и находим родовые травмы
Выбор двух миллионов разрабов, но..
Не умеет в реактивность.
Ререндеры по любому чиху.
Смешивает инициализацию и обновление, логику и шаблон.
Путается между пересозданиями и перемещением.
Все компоненты либо неуправляемые, либо неполноценные, либо ожиревшие.
Кривая эмуляция объектов через функции с хуками.
Не типизируемый VDOM на выходе.
Разобщённая экосистема со слабой поддержкой TS.
Горы бойлерплейта по мере приближения к проду.
В продолжение темы: Реактивный React, Читерские бенчмарки.
Копилка благодарностей: https://boosty.to/hyoo
⚛️ React 19 — useOptimistic
useOptimistic
— новый хук, который позволяет отобразить “оптимистичное” состояние. Оно называется “оптимистичным”, потому что мы надеемся, что запрос не свалится с ошибкой и после его выполнения состояние будет выглядеть именно так.

❓Как используется
В
useOptimistic
передаётся реальное состояние и функцию-reducerКомпонент использует “оптимистичное” состояние для рендера
Перед выполнением запроса обновляется “оптимистичное” состояние
Когда запрос завершился, нужно обновить реальное состояние
Как только реальное состояние обновилось, оптимистичное состояние обновится автоматически, так как оно передано в
useOptimistic
первым параметром.Если запрос упал с ошибкой, нужно откатить изменения в оптимистичном состоянии.
ℹ️ Первый вопрос, которым я задался, а в чём отличие от обычного setState
, путём экспериментов, вот что удалось найти:
useOptimistic
работает с формами. Работать с обычной кнопкой в SPA мне не удалось, обновление происходило только после завершения запросаuseOptimistic
работает только внутри асинхронного обработчика, что логично. Если убратьasync/await
, обновление произойдёт только после завершения запросаПараметр в useState используется только для инициализации, и игнорируется в последующих рендерах.
useOptimistic
будет сихронизироваться со значением со значением переданным первым параметром.
В любом случае, пока useOptimistic выглядит каким-то низкоуровневым API. Надеюсь скоро появится больше Best Practices.
⚛️ React 19 — use(Promise)
use
— новый хук, который позволяет считывать данные из промиса и при этом интегрирован с Suspense
и ErrorBoundary
.

Основные моменты:
На этот хук не распространяются правила хуков — его можно использовать внутри циклов и условных операторов.
Если мы используем хук
use(Promise)
, то где-то в родительском компоненте мы должны положить сам промис (не данные как мы делали раньше) в стейт (useState). Это позволяет избавиться от useEffect’а, который был нужен, чтобы запросить данные при первом рендере.Хук интегрирован с Suspense, поэтому пока промис не разрезолвится — будет показан fallback объявленный в ближайшем Suspense.
Если промис зареджектился, то будет показан
fallback
объявленный в ближайшемErrorBoundary
.
Материалы
Ближайшие события
React — Compound Components
Как-то я уже упоминал паттерн Compound Components (Составные компоненты) для React, теперь остановимся на нём немного подробнее.
ℹ️ Compound components — это подход позволяет объединить несколько компонентов в единую сущность, которая неявно имеет общее состояние. Эти компоненты тесно взаимодействуют друг с другом и работают как единое целое, представляя собой полноценный UI компонент.

? Основные характеристики:
Используется React контекст, чтобы управлять состоянием
Должен быть главный компонент, в котором хранится состояние и объявляется React контекст
Все дочерние компоненты используют состояние через React контекст
ℹ️ Он состоит из 2 простых подходов React:
Композиция компонентов
Паттерн “Провайдер” — использование контекста React
? Вначале рассмотрим подходы по отдельности
1️⃣ Что такое композиция?
Вместо вот этого
<Tile count={money} title="Стоимость" icon={<MoneyIcon/>}/>
Мы пишем вот так
<Tile>
<Title>{title}</Title>
<Number>{count}</Number>
<Icon>{icon}</Icon>
</Tile>
2️⃣ Паттерн “Провайдер”
Здесь идёт речь об обычном использовании контекста реакта, чтобы передавать какие-то данные на любую глубину дерева компонентов, минуя дочерние компоненты.
? Если объединить два этих подхода, то сможем реализовать паттерн Compound Components. Как пример, можно использовать компонент табов из библиотеки material-ui.
Препарируем StyleX и находим родовые травмы
Решение от большой компании, но..
Раздутый как CSS, так и HTML, и даже JS
Несемантичный CSS и HTML
Околонулевая типизация без автодополнения
Много бойлерплейта
Зависимость от Babel
Тормозная сборка
Сложная отладка
Копилка благодарностей: https://boosty.to/hyoo
⚛️ Атомарные обновления в Zustand
Я уже упоминал атомарные обновления, когда говорил о проблемах контекста реакта.
Я называю обновления атомарными, если компонент обновляется только тогда, когда изменяются данные, которые он использует. У контекста реакта с этим большие проблемы, но и при использовании Zustand можно выстрелить себе в ногу.
Zustand сравнивает по ссылке предыдущее и текущее значение, возвращаемое из useStore(), и если объект изменился — происходит ре-рендер.
❌ В следующем примере у нас всегда будет возвращаться новый объект, и ре-рендер произойдёт даже если изменился только age, а lastName и firstName не изменились
const {firstName, lastName} = useStore(({firstName, lastName}) => ({firstName, lastName}));
Аналогичное поведение будет и в следующем случае
const {firstName, lastName} = useStore();
✅ Есть три варианта использования значений из стейта, которые поддерживают атомарные обновления:
1️⃣ Одиночные селекторы
const firstName = useStore((state) => state.firstName)
const lastName = useStore((state) => state.lastName)
2️⃣ Селектор, который возвращает объект + shallow - функция сравнения предыдущего и нового стейтов
const {firstName, lastName} = useStore(({firstName, lastName}) => ({
firstName,
lastName
}), shallow);
3️⃣ Автосгенерированных селекторы
const firstName = useStore.use.firstName();
const lastName = useStore.use.lastName();
Накидал небольшую демку в Codesandbox
#frontend #react #statemanagement #zustand
Вклад авторов
ru_vds 1186.4aio350 633.5jarvis394 375.0artalar 272.0varanio 209.0iserdmi 208.0MrCheater 199.4EFS_programm 168.0maxfarseer 163.8comerc 161.6