Telegram Web Link
Heat.js - JavaScript Heat Map

Heat.js - библиотека для визуализации данных в виде Heat Map. Heat Map - это визуализация, которую вы можете видеть на github или gitlab, просматривая свою активность по созданию коммитов в разрезе дней. Библиотека поддерживает разные кастомизации: цвета, кнопки, текста, отступы. А также есть разные фичи. Например, экспорт в csv.

https://www.william-troup.com/heat-js/

#development #javascript #library
👍7
qr-code - web-component, реализующий анимированные QR-коды

Интересная библиотека для отрисовке QR-кодов. Библиотека позволяет делать анимированные QR-коды на svg, но при этом все API представляет собой web-компонент. Демка на странице проекта выглядит весьма хорошо.

https://github.com/bitjson/qr-code

#development #javascript #library
👍11
Дайджест за 2024-02-05 - 2024-02-09

Knip v4
Вышла 4 версия инструмента knip. Я уже писал о нем в канале - это инструмент для нахождения в проекте неиспользуемого кода. Легко встраивается в CI и быстро начинает приносить пользу. В новой версии не особо много изменений, но самое важное из них - knip теперь работает на 80% быстрее (видимо, в том числе благодаря другому изменению - теперь knip по-дефолту не анализирует использование свойств класса т.к. это требует много ресурсов)

The AHA Stack
Большой сайт, посвященный AHA-стеку: Astro + htmx + alpine.js. Если коротко, то основная идея стека крутится вокруг старого доброго веба, где сайты были легки, не было кучи JS в браузере, а основную работу делали серверы. Но все это с новым удобным и современным тулингом.

The Golden Rule of Assertions
Часто можно услышать правило "один тест - одна проверка". Проблема с этим утверждением, что его часто понимают слишком буквально, что приводит к проблемам. В статье предлагается еще 1 правило "A test must fail if, and only if, the intention behind the system is not met." (Тест должен упасть только тогда, когда намерение, заложенное в системе, не достигнуто).

Heat.js - JavaScript Heat Map
Heat.js - библиотека для визуализации данных в виде Heat Map. Heat Map - это визуализация, которую вы можете видеть на github или gitlab, просматривая свою активность по созданию коммитов в разрезе дней. Библиотека поддерживает разные кастомизации: цвета, кнопки, текста, отступы. А также есть разные фичи. Например, экспорт в csv.

qr-code - web-component, реализующий анимированные QR-коды
Интересная библиотека для отрисовке QR-кодов. Библиотека позволяет делать анимированные QR-коды на svg, но при этом все API представляет собой web-компонент. Демка на странице проекта выглядит весьма хорошо.


——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегамдрузьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
👍83🤩3
Top Front-End Tools Of 2023

Список лучших frontend-инструментов 2023-го года. Список большой и содержит всякое разное: UI-библиотеки, инструменты для CSS, AI-инструменты, инструмент для 3D-моделирования на CSS, шаблонизатор писем и многое другое. Что-то конкретно выделять не хочу, но, я думаю, каждый найдет в этом списке что-то для себя

https://www.smashingmagazine.com/2024/01/top-frontend-tools-2023/

#development #javascript #css #list
👍91
Новость для тех, кто в Новосибирске.

Тинькофф на следующей неделе (20 февраля) в своем офисе проведет неофрмальный квартирник по тестированию.
 
Темы:
— о параллельной разработке как способе достижения независимости бэклога;
— контейнерных тестах: это панацея или ловушка.

Регистируйтесь, а также зовите коллег и друзей 💛
20.02, 19:00 Нск, БЦ Кронос (ул. Советская, 5)
7💩1
How to Detect Clicks Anywhere on a Page in React

Небольшая заметка про то, как трекать любой клик в рамках страницы в React. Для многих описанное в статье не будет откровением (спойлер: обработчик вешается на body), но в статье есть интересный кусок с добавлением условной логики в глобальный обработчик на основе условия "является ли событие - событием из формы". Для меня стало открытием, что у любого события есть метод composedPath, который позволяет определить, через какие элементы проходило событие.

https://spacejelly.dev/posts/how-to-detect-clicks-anywhere-on-a-page-in-react

#development #javascript #react
👍15🔥2
Tale of a Refactor

Неплохая статья про рефакторинг кодовой базы. Прочитав название статьи, я думал, что это про реальный кейс крупного рефакторинга. Но, оказалось, что это не так. Автор рассказывает на простом примере, как с помощью рефакторинга упростить код фичи, при этом получив возможность добавлять новые под-фичи без правок в уже существующие под-фичи

Простой пример в статье: это форма оплаты. Изначально она содержит 1 тип оплаты, а затем появляются еще 2 типа оплаты. Естественно, логично предположить, что могут появиться еще новые типы оплаты.

Логичный первый порыв разработчика - поставить switch case или if else в код, связанный с рендером каждого блока формы оплаты. Однако, это плохой путь, потому что фича определенного типа оплаты получается размазанной по всей кодовой базе. Кроме того, при добавлении новых способов оплаты придется трогать большой код с условиями.

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

Что-то вроде
// Обобщенный тип
type PayForm = {
Label: Component,
Button: Component,
Body: Component
}

// В файле somePayType.tsx

/* До экспорта написан код, имплементирующий элементы формы */

export SomePayType: PayForm = {
Label: () => <div> Some Pay Type </div>,
Button: SomePayTypeButton
Body: SomePayTypeBody
}

// В самой форме

const PayFormComponent = () => {
/* всякий разный код */

// Узнаем, какой тип оплаты надо отобразить
const paymentType = useGetPaymentType();
// Получаем элементы типа оплаты
const getElements: PayForm = useGetPayTypeFormElements(paymentType);

/* код идет дальше как-то это все рендерить */
}


Статья достаточно подробно рассказывает, как разделить и верстку и логику. На самом деле итоговая имплементация в статье другая, не как у меня в блоке выше, т.к. я сильно упростил ситуацию. Но сама реализация не так важна (кстати, там все сделано через контексты), важен сам паттерн: вместо размазывания фичи по switch case следует обобщить код, а потом предоставить несколько реализаций для этого кода

https://commerce.nearform.com/blog/2024/tale-of-a-refactor/

#development #javascript #react #refactoring
8👍2👎2
Method Shorthand Syntax Considered Harmful

Небольшая статья про то, что TypeScript некорректно проверяет методы структуру, объявленные через shorthand синтаксис.

Объявим структуру Dog


interface Dog {
barkAt(dog: Dog): void;
}


Теперь скажем, что есть не только собаки, но и маленькие собаки, которые обладают уникальной способностью


interface SmallDog extends Dog {
whimper: () => void;
}


Теперь объявим собаку, которая умеет гавкать на маленьких собак


const brian: Dog = {
barkAt(smallDog: SmallDog) {
smallDog.whimper();
},
};


Т.к. каждая маленькая собака (SmallDog) является собакой (Dog), то все выглядит легально.

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


const normalDog: Dog = {
barkAt() {},
};
brian.barkAt(normalDog); // runtime error here!


Почему так происходит? Я бы объяснил это так: Typescript проверяет метод в brian на совместимость к интерфейсу, но далее в проверке не использует эти знания и считает что brian соответствует интерфейсу Dog. Т.е. по хорошему TS не должен считать расширение типа аргумента совместимым относительно оригинального типа.

Исправляется это через отказ от использования shorthand синтаксиса для объявления методов


interface Dog {
barkAt: (dog: Dog) => void;
}

interface SmallDog extends Dog {
whimper: () => void;
}


Это исправляет ситуацию, потому что TS немного по другому обрабатывает синтаксис короткого описания метода. TS считает, что такие методы могут быть и шире и уже, с точки зрения системы типов. Во всех других ситуациях допускается только сужение типов.

Это ошибка, которая может выстрелить в любом проекте т.к. держать такие нюансы постоянно в голове невозможно. Поэтому есть правило
Eslint-правило @typescript-eslint/method-signature-style, запрещающее такие объявления методов.

Для тех кто дочитал до конца пасхалка. Если перейти от этой статьи к списку всех статей, то рядом будет про то, когда необходим тайпкаст в as never. Короткое, но занимательное чтиво про то, как выстрелить себе в ногу.

https://www.totaltypescript.com/method-shorthand-syntax-considered-harmful

#development #typescript #methodShorthand
👍17👎1💩1
Towards Qwik 2.0: Lighter, Faster, Better

Команда разработки Qwik готовит релиз 2 версии фреймворка. Qwik использует концепцию Virtual Dom для работы, поэтому есть проблема восстановления Virtual Dom исходя из HTML разметки после серверного рендера. В данной статье описывается изменение решения этой проблемы во второй версии qwik, которое улучшает перформанс-метрики приложения

Если коротко, то в текущей реализации qwik ставит комментарии в HTML, а также использует кастомные атрибуты

<div q:container="paused" q:render="static-ssr" q:version="dev" q:base="/build/" q:locale q:manifest-hash="dev">
<main>
<!--qv q:s q:sref=5 q:key=-->
<!--qv q:id=7 q:key=xYL1:zl_0-->
<!--qv q:key=H1_0-->
Count:
<!--t=8-->123<!---->!
<button on:click="..." q:id="9">
+1
</button>
<!--/qv-->
<!--/qv-->
<!--/qv-->
</main>
<script type="qwik/json">{...}</script>
</div>


В новом qwik HTML-комментарии исчезнут, что делает верстку намного чище.


<div q:container="paused" q:render="static-ssr" q:version="dev" 
q:base="/build/" q:locale q:manifest-hash="dev">
<main>
Count: 123!
<button on:click="...">+1</button>
</main>
<script type="qwik/state">[...]</script>
<script type="qwik/vnode">!{{HDB1}}</script>
</div>


Тем не менее, qwik'у нужна информацию, которая была в комментариях. Эту информацию переместили в отдельный <script type="qwik/vnode"> в конце документа. При этом информация записывается в специальном формате и есть даже разбор нотации для компонента

Код компонента для верстки выше выглядит вот так:

<main>
<Counter>
<>
{'Count: '}
{signal.value}
{'!'}
<button on:click="...">+1</button>
</>
</Counter>
</main>


Информация о его виртуальных нодах выглядит следующим образом !{{HDB1}}. Это расшифровывается вот так:
- ! описывает сколько элементов надо скипнуть до <main>
- { - <main> имеет виртуальный элемент
- { - еще 1 виртуальный элемент <>
- H - H - это 7 буква алфавита (начиная с 0), поэтому из Count: 123 мы берем первые 7 символов и получаем виртуальную ноду Count:
- D - D - это 3 буква алфавита (начиная с 0), следующая текстовая нода 123
- B - это 1, поэтому следующая нода !
- 1 - описывает количество элементов, которые надо просто использовать. В нашем случае это button

Выглядит одновременно элегантно и жутко, но, очевидно, что такая нотация очень компактна.

Также виртуальные ноды станут ленивыми и будут более эффективно использовать память. Ноды будут использовать массивы вместо объектов, лениво инициализироваться, а также переиспользовать DOM-ноды

https://www.builder.io/blog/qwik-2-coming-soon

#development #qwik #javascript
👍2🔥21
Дайджест за 2024-02-12 - 2024-02-16

Top Front-End Tools Of 2023
Список лучших frontend-инструментов 2023-го года. Список большой и содержит всякое разное: UI-библиотеки, инструменты для CSS, AI-инструменты, инструмент для 3D-моделирования на CSS, шаблонизатор писем и многое другое. Что-то конкретно выделять не хочу, но, я думаю, каждый найдет в этом списке что-то для себя


How to Detect Clicks Anywhere on a Page in React
Небольшая заметка про то, как трекать любой клик в рамках страницы в React. Для многих описанное в статье не будет откровением (спойлер: обработчик вешается на body), но в статье есть интересный кусок с добавлением условной логики в глобальный обработчик на основе условия "является ли событие - событием из формы". Для меня стало открытием, что у любого события есть метод composedPath, который позволяет определить, через какие элементы проходило событие.

Tale of a Refactor
Неплохая статья про рефакторинг кодовой базы. Прочитав название статьи, я думал, что это про реальный кейс крупного рефакторинга. Но, оказалось, что это не так. Автор рассказывает на простом примере, как с помощью рефакторинга упростить код фичи, при этом получив возможность добавлять новые под-фичи без правок в уже существующие под-фичи

Простой пример в статье: это форма оплаты. Изначально она содержит 1 тип оплаты, а затем появляются еще 2 типа оплаты. Естественно, логично предположить, что могут появиться еще новые типы оплаты.

В комментариях к посту в канале мнения на счет статьи разделились: кому-то рефакторинг понравился, кому-то показалось, что стало только хуже

Method Shorthand Syntax Considered Harmful
Небольшая статья про то, что TypeScript некорректно проверяет методы структуру, объявленные через shorthand синтаксис.

Towards Qwik 2.0: Lighter, Faster, Better
Команда разработки Qwik готовит релиз 2 версии фреймворка. Qwik использует концепцию Virtual Dom для работы, поэтому есть проблема восстановления Virtual Dom исходя из HTML разметки после серверного рендера. В данной статье описывается изменение решения этой проблемы во второй версии qwik, которое улучшает перформанс-метрики приложения

——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегамдрузьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
👍6🤩1
Union, intersection, difference, and more are coming to JavaScript Sets

В Set добавляют новые методы (и вроде они уже есть в новом Chrome): unionintersectiondifferencesymmetricDifferenceisSubsetOfisSupersetOf и isDisjointFrom.

В целом, названия говорят сами за себя:
- setA.union(setB) - создает новый Set со всеми значениями из setA и setB (объединение множеств)
- setA.intersection(setB) - создает новый Set со значениями, который есть и в setA и в setB (пересечение множеств)
- setA.difference(setB) - создает новый Set со значениями, который есть в setA, но нету в setB
- setA.symmetricDifference(setB) - создает новый Set со значениями, которые есть только в одном из двух сетов
- setA.isSubsetOf(setB) - вернет true, если все значения setA есть в setB (А - подмножество Б)
- setA.isSupersetOf(setB) - вернет true, если все значения setB есть в setA (А - надмножество Б)
- setA.isDisjointFrom(setB) - вернет true, если ни одного значения в setA нет среди значений setB (множества не пересекаются)

https://www.sonarsource.com/blog/union-intersection-difference-javascript-sets/

#development #javascript #set
🔥23👍42
Immutable array updates with Array.prototype.with

Короткая заметка про новый метод массива - with. Метод создает копию массива, в котором один элемент заменен на другой.

const arr = [1,2,3]
const arr2 = arr.with(1,9)
console.log(arr); // [1,2,3]
console.log(arr2); // [1,9,3]


Также в статье упоминаются ссылки на другие новый иммутабельные методы массива
- Array.prototype.toReversed() - создает копию массива, где элементы идут в обратном порядке
- Array.prototype.toSorted() - создает копию массива, где элементы - отсортированы
- Array.prototype.toSpliced() - как splice, но создает копию массива

https://web.dev/blog/array-with

#development #javascript
👍15🔥5
23 марта пройдёт митап (или конференция, не суть) от Яндекса по фронтенду

Те кто в Москве - могут посетить очно, но также будет и онлайн-трансляция
Forwarded from Yandex for Developers
This media is not supported in your browser
VIEW IN TELEGRAM
🔥 По мотивам Дня всех влюблённых: открываем регистрацию на «Я💛Фронтенд!»

Если при разговоре о новых инструментах разработки, фреймворках и языках у вас учащается сердцебиение, коленки подкашиваются, а в глазах появляются большие мультяшные сердечки — регистрируйтесь на нашу конференцию для всех влюблённых во фронтенд!

Послушаем доклады про новые инструменты, разберём интересные кейсы из реальной практики, подискутируем с экспертами, поучаствуем в турнире Capture the Flag. И конечно, будем общаться, знакомиться и развивать наше классное сообщество. Сейчас мы только собираем полную программу, но уже известны первые спикеры:

🔸 Илья Бирман, Дизайн-бюро Артёма Горбунова. Проектирует транспортные схемы, сайты и приложения, системы навигации в общественных местах. Руководит работой дизайнеров и разработчиков, работает арт-директором Бюро и над собственными проектами.

🔸 Алексей Симоненко, HTML Academy. Начал заниматься веб-разработкой ещё в прошлом тысячелетии. Сейчас вместе с HTML Academy помогает разработчикам становиться лучше и приводит в профессию новое поколение специалистов.

🔸 Никита Балихин, Газпромбанк. Tech Lead в команде WebServiceKit Газпромбанка. Фронтендом занимается с 2018 года: любит углубляться в принципы работы инструментов, чтобы принимать более осознанные решения, и старается упростить жизнь другим разработчикам.

🔸 Никита Дубко, Яндекс. CSS-евангелист, первый сайт сверстал ещё в школьные годы. Помогает организовывать FrontendConf, MinskCSS и MinskJS. Доброжелюбный бородач в подкасте «Веб-стандарты».

Встречаемся 23 марта в Москве и онлайн.

✏️ Регистрируйтесь, если тоже разделяете нашу большую и светлую любовь к фронтенд-разработке 💛

Подписывайтесь 👉 @Yandex4Developers
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9💩61
LLRT (Low Latency Runtime) is a lightweight JavaScript runtime

LLRT (low latency runtime) - новый рантайм для запуска JS кода, который используется в AWS labmda. Рантайм оптимизирован для запуска лямбда функций и стартует в 10 раз быстрее и потребляет в 2 раза меньше ресурсов.

Под капотом используется движок QuickJS (честно говоря, не слышал про него до этого). Также поддерживаются все основные API nodejs (или же есть свои аналоги этих API)

https://github.com/awslabs/llrt

#development #javascript #aws #quickjs
👍6
Дайджест за 2024-02-19 - 2024-02-23

---

На прошлой неделе было мало новостей из-за наложения двух факторов:
- Сломался пайплайн публикации новостей. Пока чинил - чуть не потерял все конфиги n8n 🙃
- Я был немножко в отпуске

На этой неделе оба фактора устранены, так что канал возвращается в привычный ритм ежедневной публикации

---

Union, intersection, difference, and more are coming to JavaScript Sets
В Set добавляют новые методы (и вроде они уже есть в новом Chrome): union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf и isDisjointFrom.

Immutable array updates with Array.prototype.with
Короткая заметка про новый метод массива - with. Метод создает копию массива, в котором один элемент заменен на другой.


Яндекс приглашает людей посетить (офлайн или онлайн) конференцию от Яндекса про фронтенд
23 марта, 4 доклада, офлайн (Москва) и онлайн


LLRT (Low Latency Runtime) is a lightweight JavaScript runtime
LLRT (low latency runtime) - новый рантайм для запуска JS кода, который используется в AWS labmda. Рантайм оптимизирован для запуска лямбда функций и стартует в 10 раз быстрее и потребляет в 2 раза меньше ресурсов.

Под капотом используется движок QuickJS (честно говоря, не слышал про него до этого). Также поддерживаются все основные API nodejs (или же есть свои аналоги этих API)

——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегамдрузьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
👍10🔥1
WebContainers

StackBlitz разрабатывает технологию web containers. Если очень утрировано - технология позволяет запускать nodejs приложение прямо в браузере. Это, в частности, полезно для stackblitz т.к. бизнес построен вокруг предоставления окружения или песочницы для разработки приложений в браузере. Это удобно, но для запуска nodejs приложений требует запуска и обслуживания виртуалок. WebContainers решают проблему stackblitz, переводя запуск кода в браузер.

Если вам интересно поиграться с веб контейнерами - проходите по ссылке, там хорошая документация по работе с ними

https://webcontainers.io/guides/introduction

#development #javascript #webcontainer
👍51
Finishing Turborepo's migration from Go to Rust

Turborepo завершили свое 15-месячное переписывание кода 70 тысяч строк кода с Go на Rust. Сама миграция на Rust проходила так, чтобы не влиять на пользователей. В целом, это весьма непростая задача и поэтому статья интересна

Какие уроки вынесла команда Turborepo:
- Команда меняла свои подходы к сериализации данных. Сначала JSON, потом protocol-buffers, затем Capnproto. Но, если бы команда в самом начала исследовала вопрос сериализации, они бы сразу выбрали Capnproto
- У команды было несколько стратегий портирований кода. Если бы команда быстрее собирала MVP с имплементацией стратегии, команда могла бы узнать раньше о критичных подводных камнях стратегии. Соответственно, команда бы раньше узнала лучший способ миграции
- Для портирования кода очень важно качество изначального кода. Грязный, непокрытый тестами код портировать страшно - в него опасно вносить улучшающие рефакторинги.
- Перед миграцией следует хорошо проспекать техническую имплементацию. Частично миграция была сложна из-за того, что часть логики была плохо задокументирована (например, алгоритм хеширования).

https://vercel.com/blog/finishing-turborepos-migration-from-go-to-rust

#development #javascript #turbopack #migration #rust #go
👍52
Storybook 8 Beta

Команда Storybook подогревает интерес к следующему релизу. Коротко, что нам обещают в 8 сторибуке:
- Улучшение поддержки интерфейса для мобильных устройств. На случай, если кто-то смотрит storybook в мобильных браузерах
- Улучшение производительности (отключение медленных плагинов, переезд на swc)
- Улучшение инструментария для тестирования
- Поддержка серверных компонентов
- React теперь не будет являться обязательной зависимостью для storybook

https://storybook.js.org/blog/storybook-8-beta/

#development #javascript #storybook #release
7
New client-side hooks coming to React 19

Статья рассказывает про новые API, которые, предположительно, будут в react 19. Пока они доступны в канареечном релизе React

В статье рассказывается про:
- use(Promise)
- use(Context)
- Возможность передавать специфичный action в form
- useFormState
- useFormStatus
- useOptimistic
- Асинхронные транзишны

Постараюсь коротко рассказать про это API

use(Promise) позволяет дождаться выполнения Promise. Выглядит как сахар для удобного ожидания промиса внутри Suspence. Также отличается от классических хуков тем, что этот можно использовать внутри циклов и условий


import { use } from 'react';

function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
// ...
}


use(Context) это аналог useContext, но можно использовать внутри циклов и условных блоков

Также улучшили работу с формами. У форм есть проп action, в который теперь можно закидывать функцию - обработчик формы <form action={handleSubmit}>. Само по себе это мало что дает, но вместе с этой возможностью идут новые хуки, которые позволяют получить стейт и статус формы - useFormState и useFormStatus. Используя комбинацию этих API можно удобно работать с нативными формами.

Самой сложной API для меня оказался хук useOptimistic. Пришлось из статьи перейти в доку реакта, чтоб почитать подробнее, как это работает. Как я понял, useOptimistic позволяет врапнуть другой стейт и изменить его, пока врапнутый стейт не изменился. И это может быть полезно для оптимистичных апдейтов UI (техника, когда мы отрисовываем экран исходя из того, что асинхронное действие завершится успехом)

Я понял, что это работает вот так
function MyComponent() {
// Объявляем стейт
const [state, setState] = useState([])
// Врапуем его с помощью нового хука
// в optimisticState изначально будет лежать state
// В колбеке описываем, как обрабатывать оптимистичные изменения
const [optimisticState, addOptimistic] = useOptimistic(state, (state, newItem) => [...state, newItem])

// Предположим мы делаем запрос на did mount
useEffect(async () => {
const itemToAdd = {}
// добавляем оптимистичный апдейт
addOptimistic(itemToAdd)
// делаем запрос
const realItemToAdd = await fetch(url)
// после завершения запроса, меняем корневой стейт
// мы рендерим optimisticState, но после обновления state
// optimisticState обновиться до state
setState([...state, realItemToAdd])
}, [])

return <div> {optimisticState} </div>
}


Если я понял неправильно, а вы - правильно - отпишитесь, пожалуйста, в комментах, как это работает на самом деле.

Также добавили возможность делать асинхронные transitions в React. До этого было требование, чтобы транзишны были синхронными

https://marmelab.com/blog/2024/01/23/react-19-new-hooks.html

#development #javascript #react #react19 #reactHooks
👍13
2025/07/14 04:53:39
Back to Top
HTML Embed Code: