Кнопка со счётчиком: React vs Fusor

Fusor это новый способ разработки вэб приложений https://github.com/fusorjs/dom

JavaScript-библиотека для создания интерфейсов
Кнопка со счётчиком: 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