Media is too big
VIEW IN TELEGRAM
#инструмент дня
Охренеть какая штука!
https://react-explorer.com/
Это обозреватель зависимостей. Я бы даже сказал, созвездия завимимостей и сейчас вы поймёте, почему.
Потому что помимо простого дерева, которое в целом умеет строить кто угодно, тут имеется мини-карта!
Перемещаешься по карте — смотришь подсвеченные созвездия. Инспектор работает на любом реакт-сайте без отдельной установки, потому что построен по принципу React Scan — инджектит React DevTools на страницу.
Да, на минифицированном коде результат получается не очень понятный, но осознать масштаб зависимостей и связи между ними всё же позволяет.
Проект пока не открыт, но находится в открытом тестировании.
#react #analyze #dependencies
Охренеть какая штука!
https://react-explorer.com/
Это обозреватель зависимостей. Я бы даже сказал, созвездия завимимостей и сейчас вы поймёте, почему.
Потому что помимо простого дерева, которое в целом умеет строить кто угодно, тут имеется мини-карта!
Перемещаешься по карте — смотришь подсвеченные созвездия. Инспектор работает на любом реакт-сайте без отдельной установки, потому что построен по принципу React Scan — инджектит React DevTools на страницу.
Да, на минифицированном коде результат получается не очень понятный, но осознать масштаб зависимостей и связи между ними всё же позволяет.
Проект пока не открыт, но находится в открытом тестировании.
#react #analyze #dependencies
❤22👍1
#заметка дня
Не знаю, как вас, но меня очень раздражает то, что в React Router состоянием скролла надо управлять самостоятельно.
Перемещаешься по роутам, а скролл на месте остаётся. Ну типа, што.
К счастью, решение что для v5 React Router, что для v6 одинаковое:
И потом вставляете его в контекст роутинга:
Но вот я это всё по привычке написал и решил всё-таки посмотреть документацию. Ну бывает. И вот что там: https://reactrouter.com/en/main/components/scroll-restoration
Восстановление скролла теперь поставляется из коробки! И умеет гораздо больше, чем просто скроллить наверх. Правда, требует изменения корневого роутера. Благо, это несложно.
Например, можно сгенерировать ключ для маршрута и на этом маршруте скролл будет восстанавливаться в предыдущее состояние по заданным вами правилам.
По-моему, очень круто. И хорошо, что решение официальное.
#react #router #бородач
Не знаю, как вас, но меня очень раздражает то, что в React Router состоянием скролла надо управлять самостоятельно.
Перемещаешься по роутам, а скролл на месте остаётся. Ну типа, што.
К счастью, решение что для v5 React Router, что для v6 одинаковое:
function ScrollToTop() {
const { pathname } = useLocation();
useLayoutEffect(() => {
document.documentElement.scrollTo(0, 0);
}, [pathname]);
return null;
}
И потом вставляете его в контекст роутинга:
<BrowserRouter>
<Routes>
...
</Routes>
<ScrollToTop/>
</BrowserRouter>
Но вот я это всё по привычке написал и решил всё-таки посмотреть документацию. Ну бывает. И вот что там: https://reactrouter.com/en/main/components/scroll-restoration
Восстановление скролла теперь поставляется из коробки! И умеет гораздо больше, чем просто скроллить наверх. Правда, требует изменения корневого роутера. Благо, это несложно.
Например, можно сгенерировать ключ для маршрута и на этом маршруте скролл будет восстанавливаться в предыдущее состояние по заданным вами правилам.
По-моему, очень круто. И хорошо, что решение официальное.
#react #router #бородач
👍13❤3🤡1
This media is not supported in your browser
VIEW IN TELEGRAM
#инструмент дня
Вы только посмотрите на эту красоту!
Да, я в курсе, что компонентов для красивого прокручивания цифр у нас какое-то невероятное количество, но до сих пор не было ничего настолько универсального и простого в использовании.
И не только для React! Vue и Svelte тоже там.
Итак, встречайте: NumberFlow от Максвелла Барвиана.
GitHub: https://github.com/barvian/number-flow
Документация и демо: https://number-flow.barvian.me/
Настраивается формат чисел, параметры анимированных переходов. И, собственно, никаких скрытых зависимостей.
Прекрасное.
#react #number #transition #бородач
Вы только посмотрите на эту красоту!
Да, я в курсе, что компонентов для красивого прокручивания цифр у нас какое-то невероятное количество, но до сих пор не было ничего настолько универсального и простого в использовании.
И не только для React! Vue и Svelte тоже там.
Итак, встречайте: NumberFlow от Максвелла Барвиана.
GitHub: https://github.com/barvian/number-flow
Документация и демо: https://number-flow.barvian.me/
Настраивается формат чисел, параметры анимированных переходов. И, собственно, никаких скрытых зависимостей.
Прекрасное.
#react #number #transition #бородач
❤31
Дэн «наше всё» Абрамов разродился статьёй!
React for Two Computers
— Почему мой компонент работает в браузере, но не на сервере?
— Потому что у тебя теперь два компьютера. Привыкай.
💥 Что вообще происходит?
Раньше React жил в браузере и радовался жизни: всё происходило на клиенте, стейт в useState, кликнули — перерендерили.
А теперь у нас появился второй «компьютер» — сервер. С серверными компонентами, приватными API, тяжёлыми вычислениями и всем остальным. И теперь React — это не просто `
-
-
🧠 React теперь работает в двух мирах:
- Сервер — отвечает за данные, безопасность и тяжёлую работу
- Клиент — за мгновенные отклики, интерактив и состояние
Они живут в разных средах, но должны строить один интерфейс. И вот тут начинается веселье.
🧩 Но в чём подвох?
Абрамов говорит прямо: разделение компонентов на клиентские и серверные — это боль.
- Хочешь использовать хук? Прости, сервер не умеет
- Хочешь загрузить данные? Сервер умеет, но клиент не должен знать как
- Хочешь просто написать код? Удачи с этими
🧠 Примеры из статьи
-
-
И вдруг возникает челлендж: а как показать список
Ответ: через пропсы, границы, и много боли.
📦 React как Lego из серверных и клиентских кусочков
Абрамов не просто жалуется — он исследует. Он пытается найти модель мышления, при которой:
- Ты не дублируешь код
- UI остаётся отзывчивым
- Компоненты переиспользуемы
- И при этом ты не хочешь сжечь проект через неделю
Он говорит: возможно, будущее React — это когда мы думаем не в терминах "компоненты", а в терминах "где этот кусок должен жить?"
🎥 Есть и видео!
Если лень читать или хочется живого контекста — Дэн рассказал всё это на конференции React Conf 2024.
Там много примеров и визуальных пояснений.
🧨 Финалим
Пока что — это боль.
Но если мы научимся думать в этой модели — React станет по-настоящему мощным инструментом для приложений нового поколения.
🔗 Читать статью целиком
📺 Смотреть видео React Conf 2024
#react #frontend #абрамов #servercomponents
React for Two Computers
— Почему мой компонент работает в браузере, но не на сервере?
— Потому что у тебя теперь два компьютера. Привыкай.
💥 Что вообще происходит?
Раньше React жил в браузере и радовался жизни: всё происходило на клиенте, стейт в useState, кликнули — перерендерили.
А теперь у нас появился второй «компьютер» — сервер. С серверными компонентами, приватными API, тяжёлыми вычислениями и всем остальным. И теперь React — это не просто `
f(state)`, а f(data, state), где:-
data — с сервера, рендерится один раз -
state — в браузере, реагирует на действия пользователя 🧠 React теперь работает в двух мирах:
- Сервер — отвечает за данные, безопасность и тяжёлую работу
- Клиент — за мгновенные отклики, интерактив и состояние
Они живут в разных средах, но должны строить один интерфейс. И вот тут начинается веселье.
🧩 Но в чём подвох?
Абрамов говорит прямо: разделение компонентов на клиентские и серверные — это боль.
- Хочешь использовать хук? Прости, сервер не умеет
- Хочешь загрузить данные? Сервер умеет, но клиент не должен знать как
- Хочешь просто написать код? Удачи с этими
use client, use server, границами, пропами и тайпингом🧠 Примеры из статьи
-
<Counter /> — типичный клиентский компонент. Быстрый отклик, стейт, интерактив -
<PostPreview /> — серверный. Может грузить пост из базы и вообще не попадать в бандл клиентаИ вдруг возникает челлендж: а как показать список
<PostPreview />, а рядом <Counter /> для лайков? Как они будут жить вместе?Ответ: через пропсы, границы, и много боли.
📦 React как Lego из серверных и клиентских кусочков
Абрамов не просто жалуется — он исследует. Он пытается найти модель мышления, при которой:
- Ты не дублируешь код
- UI остаётся отзывчивым
- Компоненты переиспользуемы
- И при этом ты не хочешь сжечь проект через неделю
Он говорит: возможно, будущее React — это когда мы думаем не в терминах "компоненты", а в терминах "где этот кусок должен жить?"
🎥 Есть и видео!
Если лень читать или хочется живого контекста — Дэн рассказал всё это на конференции React Conf 2024.
Там много примеров и визуальных пояснений.
🧨 Финалим
«React теперь не просто библиотека для UI. Это **координация между двумя средами исполнения**. Между клиентом и сервером. И это сложно. Но в этом сила.»
Пока что — это боль.
Но если мы научимся думать в этой модели — React станет по-настоящему мощным инструментом для приложений нового поколения.
🔗 Читать статью целиком
📺 Смотреть видео React Conf 2024
#react #frontend #абрамов #servercomponents
1🤡14👍12❤3🫡1
Media is too big
VIEW IN TELEGRAM
#инструмент дня
Так вышло, что в своей карьере я умудрился поработать в компании, которая хотела сделать стримы на веб-сайте своей основной фишкой. С тех пор HLS, RTP и nginx-rtmp-plugin были моими друзьями.
Но возможности по микшированию видео, звука и изображений прямо на веб-странице тогда были весьма ограничены или просто сложны. Работали через OBS, хотя даже он был в весьма зачаточном состоянии.
Но сегодня я наткнулся на нечто прекрасное: https://compositor.live/
Это набор React-компонентов и медиасервер, который позволяет стримить видео и микшировать несколько потоков, управляя ими как обычными компонентами и элементами страницы!
Можно построить нечто аналогичное Google Meet за считанные дни.
Вырезать зелёный экран, добавить текст, поменять видео местами, наложить блупер — всё на месте. Напоминает react-three-fiber по своей сути.
#react #video #mixer #media #stream #бородач
Так вышло, что в своей карьере я умудрился поработать в компании, которая хотела сделать стримы на веб-сайте своей основной фишкой. С тех пор HLS, RTP и nginx-rtmp-plugin были моими друзьями.
Но возможности по микшированию видео, звука и изображений прямо на веб-странице тогда были весьма ограничены или просто сложны. Работали через OBS, хотя даже он был в весьма зачаточном состоянии.
Но сегодня я наткнулся на нечто прекрасное: https://compositor.live/
Это набор React-компонентов и медиасервер, который позволяет стримить видео и микшировать несколько потоков, управляя ими как обычными компонентами и элементами страницы!
Можно построить нечто аналогичное Google Meet за считанные дни.
Вырезать зелёный экран, добавить текст, поменять видео местами, наложить блупер — всё на месте. Напоминает react-three-fiber по своей сути.
#react #video #mixer #media #stream #бородач
👍26❤8
#статья дня
Дэн наше всё Абрамов недавно написал статью о новом способе передачи данных с сервера — Progressive JSON. Это не просто использование курсоров для пагинации, как в том же JSON:API, а настоящий поток данных, где структура JSON передаётся частями, по мере её готовности.
Вообще, много пишет последнее время. Это хорошо!
Зачем нужно? Собственно, для работы React Server Components в том числа!
Пример такого потока:
Видите заглушку $1? Позже — в том же потоке! — приходит следующий кусок:
На стороне клиента это будет выглядеть как:
Комментарии в статье подгружаются по мере их поступления, и клиент может начать отображать контент сразу, даже если не все данные ещё доступны. Этот подход позволяет эффективно загружать и рендерить сложные интерфейсы, улучшая отзывчивость приложения.
Если вам интересна тема оптимизации загрузки данных, стоит прочитать статью Дэна: Progressive JSON.
А, или посмотреть в формате видеоподкаста! Тут: https://www.youtube.com/watch?v=MaMQLNBZz64
#react #json #rsc
Дэн наше всё Абрамов недавно написал статью о новом способе передачи данных с сервера — Progressive JSON. Это не просто использование курсоров для пагинации, как в том же JSON:API, а настоящий поток данных, где структура JSON передаётся частями, по мере её готовности.
Вообще, много пишет последнее время. Это хорошо!
Зачем нужно? Собственно, для работы React Server Components в том числа!
Пример такого потока:
{
"header": "Welcome to my blog",
"post": "$1",
"footer": "Hope you like it"
}
Видите заглушку $1? Позже — в том же потоке! — приходит следующий кусок:
/* $1 */
{
"content": "This is my article",
"comments": "$2"
}
На стороне клиента это будет выглядеть как:
{
"header": "Welcome to my blog",
"post": {
"content": "This is my article",
"comments": new Promise(/* ... not yet resolved ... */),
},
"footer": "Hope you like it"
}
Комментарии в статье подгружаются по мере их поступления, и клиент может начать отображать контент сразу, даже если не все данные ещё доступны. Этот подход позволяет эффективно загружать и рендерить сложные интерфейсы, улучшая отзывчивость приложения.
Если вам интересна тема оптимизации загрузки данных, стоит прочитать статью Дэна: Progressive JSON.
А, или посмотреть в формате видеоподкаста! Тут: https://www.youtube.com/watch?v=MaMQLNBZz64
#react #json #rsc
👍22❤6👎2
#статья дня
Можно ли заменить стейт-менеджеры — простым localStorage?
Вопрос не настолько абсурдный, как может показаться, хотя понятное дело, что многие из вас уже знают ответ.
Давайте подумаем:
> Не всё должно быть постоянным. Допустим, у тебя открыто модальное окно. Перезагрузил страницу — и оно снова открыто, потому что значение сохранилось в localStorage. Абсурдный UX.
> Нет реактивности. Если просто читать из localStorage, React не узнает, что данные изменились, и не перерендерит компонент. Придётся вручную дёргать setState.
> Событие storage работает не так. Оно срабатывает только в других вкладках, а не в той, где ты вызвал localStorage.setItem(). То есть синхронизацию внутри приложения оно не решает.
> Ограничения. Только строки, лимит около 5 МБ, возможные ошибки при парсинге JSON, коллизии ключей. Всё это требует дополнительных костылей.
> SSR недоступен. На сервере localStorage просто не существует, и код падает с ошибкой.
localStorage и, частично, sessionStorage отлично подходят для мелочей:
> выбор темы,
> сохранение введённых данных формы,
> открытая вкладка меню,
Но как только речь заходит о данных, которые должны синхронно обновляться в разных компонентах и вызывать ререндер — нужен Context или полноценный state-менеджер.
Итак: localStorage — это удобное дополнение к Context/Redux/Zustand, но не замена. Он решает задачу «сохранить между сессиями», а не «синхронизировать состояние внутри React».
А если хотите подробностей — собственно, статья от Нади Макаревич: https://www.developerway.com/posts/local-storage-instead-of-context
Не думаю, что олды что-то найдут новое (разве что лишний раз поржать над событием storage), но у новичков вопросы такого плана возникают постоянно.
#react #localstorage
Можно ли заменить стейт-менеджеры — простым localStorage?
Вопрос не настолько абсурдный, как может показаться, хотя понятное дело, что многие из вас уже знают ответ.
Давайте подумаем:
> Не всё должно быть постоянным. Допустим, у тебя открыто модальное окно. Перезагрузил страницу — и оно снова открыто, потому что значение сохранилось в localStorage. Абсурдный UX.
> Нет реактивности. Если просто читать из localStorage, React не узнает, что данные изменились, и не перерендерит компонент. Придётся вручную дёргать setState.
> Событие storage работает не так. Оно срабатывает только в других вкладках, а не в той, где ты вызвал localStorage.setItem(). То есть синхронизацию внутри приложения оно не решает.
> Ограничения. Только строки, лимит около 5 МБ, возможные ошибки при парсинге JSON, коллизии ключей. Всё это требует дополнительных костылей.
> SSR недоступен. На сервере localStorage просто не существует, и код падает с ошибкой.
localStorage и, частично, sessionStorage отлично подходят для мелочей:
> выбор темы,
> сохранение введённых данных формы,
> открытая вкладка меню,
Но как только речь заходит о данных, которые должны синхронно обновляться в разных компонентах и вызывать ререндер — нужен Context или полноценный state-менеджер.
Итак: localStorage — это удобное дополнение к Context/Redux/Zustand, но не замена. Он решает задачу «сохранить между сессиями», а не «синхронизировать состояние внутри React».
А если хотите подробностей — собственно, статья от Нади Макаревич: https://www.developerway.com/posts/local-storage-instead-of-context
Не думаю, что олды что-то найдут новое (разве что лишний раз поржать над событием storage), но у новичков вопросы такого плана возникают постоянно.
#react #localstorage
❤10🫡1
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня
И #тред дня, и #статья дня... Сегодня всё и сразу от Джоша Комо.
И речь пойдёт о недооценённом хуке в React: useDeferredValue.
Итак, некоторое время назад Джош выпустил свой инструмент для создания красиво выглядящих теней (да-да, drop-shadow просто уже недостаточно). И одной из проблем инструмента стала... дёрганая реакция на движение ползунков. Как будто мало FPS.
Начав разбирать проблему, Джош понял, что событие onChange происходит очень часто, за это время надо успеть сгенерировать тень, потом отрисовать её, потом вставить код в редактор для копирования. А редактор, естественно, ещё пытается этот самый код подсветить.
Но что нам нужно? Нам ведь сначала нужен результат, а уже потом — код. Так почему бы не заполнить код чуть позже, не нагружая систему?
И именно для этого и нужен хук useDeferredValue. Данные молучим только когда основной процесс рендеринга завершится. Буквально ленивое выполнение.
Собственно, тред и статья если кто предпочитает подробности. Там, как всегда, шикарно.
Будьте разумно ленивыми, котаны!
#react #hook #бородач
И #тред дня, и #статья дня... Сегодня всё и сразу от Джоша Комо.
И речь пойдёт о недооценённом хуке в React: useDeferredValue.
Итак, некоторое время назад Джош выпустил свой инструмент для создания красиво выглядящих теней (да-да, drop-shadow просто уже недостаточно). И одной из проблем инструмента стала... дёрганая реакция на движение ползунков. Как будто мало FPS.
Начав разбирать проблему, Джош понял, что событие onChange происходит очень часто, за это время надо успеть сгенерировать тень, потом отрисовать её, потом вставить код в редактор для копирования. А редактор, естественно, ещё пытается этот самый код подсветить.
Но что нам нужно? Нам ведь сначала нужен результат, а уже потом — код. Так почему бы не заполнить код чуть позже, не нагружая систему?
И именно для этого и нужен хук useDeferredValue. Данные молучим только когда основной процесс рендеринга завершится. Буквально ленивое выполнение.
Собственно, тред и статья если кто предпочитает подробности. Там, как всегда, шикарно.
Будьте разумно ленивыми, котаны!
#react #hook #бородач
❤21
#такое дня
12 сентября Cloudflare устроили себе эпичный автогол: https://blog.cloudflare.com/deep-dive-into-cloudflares-sept-12-dashboard-and-api-outage/
В новой версии дашборда React-хук внезапно превратился в пулемёт: вместо одного вызова useEffect он триггерился десятки раз подряд. Причина до обидного банальна — в зависимостях лежал объект, который пересоздавался на каждом рендере.
В итоге фронтенд начал долбить Tenant Service шквалом запросов, сервис не выдержал нагрузки и лёг. А вместе с ним посыпалась и авторизация всех API-запросов, так что по системе пошёл массовый вал 5xx.
И это ведь не какая-то загадочная бага в ядре Linux, а ошибка из разряда «прочитай первую статью про хуки». Её должны были отловить ещё на ревью.
Но видимо, ревью формальное, нагрузочных тестов не было вовсе, а сценарии перегруза и защиты от них решили «подразумеваются».
Рекомендую прочесть статью хотя бы ради того, чтобы узнать, что такое Thundering Herd :)
Особо смешно, что индустрия уже много лет живёт с готовыми решениями этих проблем. Есть react-query, SWR и куча других библиотек, которые умеют кешировать данные, контролировать повторные запросы, дебаунсить и ретраить без того, чтобы фронтенд превращался в DoS-атаку на свой же бэкенд. Но всё это дружно игнорируется, и в прод выкатываются костыли уровня «ну вроде работает».
В итоге — глобальная недоступность сервиса, вызванная элементарным skill issue. Ошибка, которую любой толковый джун заметил бы на месте, внезапно кладёт критичную часть инфраструктуры одной из крупнейших сетевых компаний в мире.
И нет, это не React виноват, дамы и господа, даже не начинайте.
Ирония в том, что чем больше индустрия пишет о «best practices» и «production-ready», тем чаще мы видим вот такие падения на ровном месте.
#react #useeffect #hook
12 сентября Cloudflare устроили себе эпичный автогол: https://blog.cloudflare.com/deep-dive-into-cloudflares-sept-12-dashboard-and-api-outage/
В новой версии дашборда React-хук внезапно превратился в пулемёт: вместо одного вызова useEffect он триггерился десятки раз подряд. Причина до обидного банальна — в зависимостях лежал объект, который пересоздавался на каждом рендере.
В итоге фронтенд начал долбить Tenant Service шквалом запросов, сервис не выдержал нагрузки и лёг. А вместе с ним посыпалась и авторизация всех API-запросов, так что по системе пошёл массовый вал 5xx.
И это ведь не какая-то загадочная бага в ядре Linux, а ошибка из разряда «прочитай первую статью про хуки». Её должны были отловить ещё на ревью.
Но видимо, ревью формальное, нагрузочных тестов не было вовсе, а сценарии перегруза и защиты от них решили «подразумеваются».
Рекомендую прочесть статью хотя бы ради того, чтобы узнать, что такое Thundering Herd :)
Особо смешно, что индустрия уже много лет живёт с готовыми решениями этих проблем. Есть react-query, SWR и куча других библиотек, которые умеют кешировать данные, контролировать повторные запросы, дебаунсить и ретраить без того, чтобы фронтенд превращался в DoS-атаку на свой же бэкенд. Но всё это дружно игнорируется, и в прод выкатываются костыли уровня «ну вроде работает».
В итоге — глобальная недоступность сервиса, вызванная элементарным skill issue. Ошибка, которую любой толковый джун заметил бы на месте, внезапно кладёт критичную часть инфраструктуры одной из крупнейших сетевых компаний в мире.
И нет, это не React виноват, дамы и господа, даже не начинайте.
Ирония в том, что чем больше индустрия пишет о «best practices» и «production-ready», тем чаще мы видим вот такие падения на ровном месте.
#react #useeffect #hook
1🤡17👍10❤6🫡1
#зомби дня
Sanity написали про текущее состояние styled-components.
Библиотека официально с марта, если помните, в maintenance-режиме: новых фич ждать не стоит, и главная проблема — производительность. В React 18 она не использует
В Sanity сделали форк и оптимизировали вставку стилей, убрали лишние костыли и адаптировали всё под React 19. У Linear, после замены пакета на этот форк, рендер ускорился до 40% без переписывания компонентов.
Для React 18 они предлагают
При этом авторы подчёркивают, что форк — временное решение. В ближайшей перспективе они советуют перестать писать новые компоненты на styled-components и выбрать альтернативу вроде vanilla-extract, Tailwind или Panda CSS, постепенно перенося стили.
Учитывая, что у нас в компании ещё огромное количество зависимостей от Styled Components (ведь все в целом ждали несколько иного развития событий), переход на форк, чтобы сгладить ситуацию во время апгрейда на React 18 и 19, кажется разумным. Тем более, что текущее состояние старых компонентов давно заморожено.
#css #react #sc
Sanity написали про текущее состояние styled-components.
Библиотека официально с марта, если помните, в maintenance-режиме: новых фич ждать не стоит, и главная проблема — производительность. В React 18 она не использует
useInsertionEffect, из-за чего вставка стилей тормозит рендер. И это ощутимо.В Sanity сделали форк и оптимизировали вставку стилей, убрали лишние костыли и адаптировали всё под React 19. У Linear, после замены пакета на этот форк, рендер ускорился до 40% без переписывания компонентов.
Для React 18 они предлагают
@sanity/styled-components, для React 19 — @sanity/css-in-js.При этом авторы подчёркивают, что форк — временное решение. В ближайшей перспективе они советуют перестать писать новые компоненты на styled-components и выбрать альтернативу вроде vanilla-extract, Tailwind или Panda CSS, постепенно перенося стили.
Учитывая, что у нас в компании ещё огромное количество зависимостей от Styled Components (ведь все в целом ждали несколько иного развития событий), переход на форк, чтобы сгладить ситуацию во время апгрейда на React 18 и 19, кажется разумным. Тем более, что текущее состояние старых компонентов давно заморожено.
#css #react #sc
👍10🤡4🫡2
#новость дня
React наконец-то съехал от родителей: https://engineering.fb.com/2025/10/07/open-source/introducing-the-react-foundation-the-new-home-for-react-react-native/
Когда-то это был домашний проект Facebook, призванный подлатать их новостную ленту и упростить генерацию мешанины в текстах рекламных объявлений (вы ещё помните такое? рассказать?). Потом код открыли — и случайно изобрели современный фронтенд. JSX, компонентный подход, декларативность — пропаганда вот этого вот всего.
Но чем популярнее становился React, тем нелепее выглядело, что он всё ещё приписан к Meta. Комьюнити писало RFC, спорило в GitHub-тредах, Дэн наше всё писал длинные эссе, а потом всё равно все ждали, пока кто-нибудь из Menlo Park скажет «одобрено». React давно жил как независимый проект — просто юридически оставался семейной реликвией.
Пока запрещенная в России террористическая организация Meta занималась метавселенными, React-мир крутился вокруг Vercel и Next.js. Именно они сделали React пригодным для продакшена: собрали все фичи в удобную платформу и задали курс для всей экосистемы. По сути, Vercel уже несколько лет пишет реальную «дорожную карту» React, а теперь это просто оформилось официально.
Так что да — теперь есть React Foundation, под крылом Linux Foundation. В совете — Meta, Microsoft, Amazon, Vercel, Expo и прочие большие люди. Meta оставляет три миллиона долларов на карманные расходы и обещает не мешать.
Linux Foundation, гы-гы, вот так и настанет вендекапец. Слышали, там уже поиск на React Native?
Ну что, котаны, давно пора было? Или надо было в Apache Foundation? :)
P. S. а ещё я забыл написать что ещё 7 октября вышел React Compiler 1.0, но я его сам что-то ещё не опробовал.
#react #meta #linux
React наконец-то съехал от родителей: https://engineering.fb.com/2025/10/07/open-source/introducing-the-react-foundation-the-new-home-for-react-react-native/
Когда-то это был домашний проект Facebook, призванный подлатать их новостную ленту и упростить генерацию мешанины в текстах рекламных объявлений (вы ещё помните такое? рассказать?). Потом код открыли — и случайно изобрели современный фронтенд. JSX, компонентный подход, декларативность — пропаганда вот этого вот всего.
Но чем популярнее становился React, тем нелепее выглядело, что он всё ещё приписан к Meta. Комьюнити писало RFC, спорило в GitHub-тредах, Дэн наше всё писал длинные эссе, а потом всё равно все ждали, пока кто-нибудь из Menlo Park скажет «одобрено». React давно жил как независимый проект — просто юридически оставался семейной реликвией.
Пока запрещенная в России террористическая организация Meta занималась метавселенными, React-мир крутился вокруг Vercel и Next.js. Именно они сделали React пригодным для продакшена: собрали все фичи в удобную платформу и задали курс для всей экосистемы. По сути, Vercel уже несколько лет пишет реальную «дорожную карту» React, а теперь это просто оформилось официально.
Так что да — теперь есть React Foundation, под крылом Linux Foundation. В совете — Meta, Microsoft, Amazon, Vercel, Expo и прочие большие люди. Meta оставляет три миллиона долларов на карманные расходы и обещает не мешать.
Linux Foundation, гы-гы, вот так и настанет вендекапец. Слышали, там уже поиск на React Native?
Ну что, котаны, давно пора было? Или надо было в Apache Foundation? :)
P. S. а ещё я забыл написать что ещё 7 октября вышел React Compiler 1.0, но я его сам что-то ещё не опробовал.
#react #meta #linux
1👍11❤3
#видео дня
Алекс Ильинов и Алёна Батицкая (Дока) выкатили весьма интересный формат короткого видеоподкаста, больше напоминающий теннисный матч: Code Cleanup.
Подкаст будет посвящён рефакторингу кода. Почему будет? Ну, потому что вот только-только первый выпуск вышел, посвящённый рефакторингу форм в React 19: https://youtu.be/JdMGSgh9uHA
Не просто «а давайте всё поменяем», а почему конкретно и зачем. Ведущие подкидывают друг-другу вопросы и предложения, подхватывая на лету. Потому, собственно, и теннисный матч.
Я очень надеюсь, у них хватит сил продолжать, поскольку получилось весьма забавно и по делу. А ещё я тут сдул пыль с одного старого проекта, потому для меня ещё и вовремя.
#react #podcast #refactoring
Алекс Ильинов и Алёна Батицкая (Дока) выкатили весьма интересный формат короткого видеоподкаста, больше напоминающий теннисный матч: Code Cleanup.
Подкаст будет посвящён рефакторингу кода. Почему будет? Ну, потому что вот только-только первый выпуск вышел, посвящённый рефакторингу форм в React 19: https://youtu.be/JdMGSgh9uHA
Не просто «а давайте всё поменяем», а почему конкретно и зачем. Ведущие подкидывают друг-другу вопросы и предложения, подхватывая на лету. Потому, собственно, и теннисный матч.
Я очень надеюсь, у них хватит сил продолжать, поскольку получилось весьма забавно и по делу. А ещё я тут сдул пыль с одного старого проекта, потому для меня ещё и вовремя.
#react #podcast #refactoring
👍15
#инструмент дня
Нашел тут ESLint-плагин eslint-plugin-react-you-might-not-need-an-effect, вдохновлённый одноимённой статьёй из официальной документации React.
Он пытается отучить нас пихать
React, впрочем, не стоит на месте: в версии 19.1 появился useEffectEvent, который позволяет выносить логику из эффектов и вроде бы делает их чище и предсказуемее.
Но к этому моменту все уже слегка устали от того, что каждый релиз приносит ещё один способ «наконец-то правильно» писать эффекты.
Плагин же решает вопрос просто: он показывает, где
#react #eslint
Нашел тут ESLint-плагин eslint-plugin-react-you-might-not-need-an-effect, вдохновлённый одноимённой статьёй из официальной документации React.
Он пытается отучить нас пихать
useEffect везде, где что-то меняется, и напоминает, что часто эффекты просто не нужны — всё можно выразить данными и рендером.React, впрочем, не стоит на месте: в версии 19.1 появился useEffectEvent, который позволяет выносить логику из эффектов и вроде бы делает их чище и предсказуемее.
Но к этому моменту все уже слегка устали от того, что каждый релиз приносит ещё один способ «наконец-то правильно» писать эффекты.
Плагин же решает вопрос просто: он показывает, где
useEffect вам, скорее всего, не нужен. Без философии — только суровая плётка погонщика.#react #eslint
👍14❤1
#заметка дня
Итак, ты хочешь использовать Tanstack (React) Query для запроса данных, но хочешь делать это по-запросу, а не декларативно?
Ни слова больше! Используй useMutation, даже если это контр-интуитивно. Мутации — они по своей природе императивные, их нужно вызывать ручками в нужный момент.
Вот только есть один нюанс: мутацию — опять же, по-определению — нельзя отменить. Если требование изменений ушло на сервер — слишком много телодвижений нужно, чтобы перестать это делать. Нет уверенности в том, что изменения ещё не применились.
Да, даже если мутация, на самом деле, ничего не делает.
А мне надо было, стояла задача подключаться к источникам данных, но иметь возможность это подключение (или несколько) прекратить в любой момент без создания, собственно, токена.
А вот запрос — отменить можно. Прямо в документации: или посылая AbortSignal, или вызывая соответствующий метод клиента, cancelQueries, по ключу запроса.
С мутацией сильно больше телодвижений.
Кстати, вы же в курсе, что ключи действуют как wildcard? todo среагирует и на todo-1, и на todo-2 и так далее. Это не самая очевидная вещь.
Ладно, но всё же, как вызвать запрос императивно?
Очень просто: комбинацией из refetch и параметра enabled в конфигурации хука:
И используем как обычно:
Секрет в том, что теперь refetch можно передать куда угодно и дёрнуть.
Естественно, всегда создавайте кастомные хуки для useQuery и useMutation. Не держите логику в компоненте.
Я ещё люблю отключать refetch по фокусу на окне и по потере соединения. Про идиотскую ситуацию с неправильным определением потери соединения я уже писал ранее.
#react #tanstack #query #бородач
Итак, ты хочешь использовать Tanstack (React) Query для запроса данных, но хочешь делать это по-запросу, а не декларативно?
Ни слова больше! Используй useMutation, даже если это контр-интуитивно. Мутации — они по своей природе императивные, их нужно вызывать ручками в нужный момент.
Вот только есть один нюанс: мутацию — опять же, по-определению — нельзя отменить. Если требование изменений ушло на сервер — слишком много телодвижений нужно, чтобы перестать это делать. Нет уверенности в том, что изменения ещё не применились.
Да, даже если мутация, на самом деле, ничего не делает.
А мне надо было, стояла задача подключаться к источникам данных, но иметь возможность это подключение (или несколько) прекратить в любой момент без создания, собственно, токена.
А вот запрос — отменить можно. Прямо в документации: или посылая AbortSignal, или вызывая соответствующий метод клиента, cancelQueries, по ключу запроса.
С мутацией сильно больше телодвижений.
Кстати, вы же в курсе, что ключи действуют как wildcard? todo среагирует и на todo-1, и на todo-2 и так далее. Это не самая очевидная вещь.
Ладно, но всё же, как вызвать запрос императивно?
Очень просто: комбинацией из refetch и параметра enabled в конфигурации хука:
useQuery<TokenResponse>({
enabled: false,
retry: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
refetchInterval: false,
queryKey: ['connecting', dsId, connectionKey],
queryFn: async ({ signal }) => {
signal?.addEventListener('abort', cancelConnection);
...
}
});
И используем как обычно:
const {
data: profile,
refetch: startConnection,
connectionStatus,
isFetching: isFetchingConnection,
isError,
} = useConnect(dataSource, ...);
Секрет в том, что теперь refetch можно передать куда угодно и дёрнуть.
Естественно, всегда создавайте кастомные хуки для useQuery и useMutation. Не держите логику в компоненте.
Я ещё люблю отключать refetch по фокусу на окне и по потере соединения. Про идиотскую ситуацию с неправильным определением потери соединения я уже писал ранее.
#react #tanstack #query #бородач
❤7👎1🫡1
#презентация дня
Я тут сегодня успел на митапе побывать! И не просто побывать, а ещё и спикером там был.
Митап — Design System Breakfast, который лидит Варя Степанова — посвящён, как несложно догадаться, дизайн-системам в разных их проявлениях. И сегодня я там презентовал открытую мной недавно возможность писать функциональные и поведенческие тесты прямо в сторях, а потом запускать их в Jest как локально, так и в CI/CD.
И называется эта вся прелесть — Storybook Interactions. И, естественно, одним только Jest дело не ограничивается, скорее даже наоборрот — официальная их рекомендация это использование Vitest и Playwright. Но у нас в команде уже есть сформированная экосистема.
Итак, презентация: https://docs.google.com/presentation/d/1hpAt3y4zE1U8vRhY_IfmM3NEeY8qCe9QdKnQLAJF8oo/edit?usp=sharing
Ну и, конечно же, пример на гитхабе: https://github.com/bekharsky/when-jest-met-storybook
Стек: Vite, React 19, MSW, MUI, React Router, Tanstack Query, Storybook 9 и Jest с SWC.
Если нужно больше подробностей или хотите стрим прямо здесь на канале — требуйте, не стесняйтесь, котаны!
#react #design #storybook #ui #test
Я тут сегодня успел на митапе побывать! И не просто побывать, а ещё и спикером там был.
Митап — Design System Breakfast, который лидит Варя Степанова — посвящён, как несложно догадаться, дизайн-системам в разных их проявлениях. И сегодня я там презентовал открытую мной недавно возможность писать функциональные и поведенческие тесты прямо в сторях, а потом запускать их в Jest как локально, так и в CI/CD.
И называется эта вся прелесть — Storybook Interactions. И, естественно, одним только Jest дело не ограничивается, скорее даже наоборрот — официальная их рекомендация это использование Vitest и Playwright. Но у нас в команде уже есть сформированная экосистема.
Итак, презентация: https://docs.google.com/presentation/d/1hpAt3y4zE1U8vRhY_IfmM3NEeY8qCe9QdKnQLAJF8oo/edit?usp=sharing
Ну и, конечно же, пример на гитхабе: https://github.com/bekharsky/when-jest-met-storybook
Стек: Vite, React 19, MSW, MUI, React Router, Tanstack Query, Storybook 9 и Jest с SWC.
Если нужно больше подробностей или хотите стрим прямо здесь на канале — требуйте, не стесняйтесь, котаны!
#react #design #storybook #ui #test
👍8👎2
#молния дня
В React обнаружили критическую уязвимость в механизме серверных компонентов (React Server Components). Из-за ошибки в том, как React разбирает входящие данные, сервер может попытаться выполнить вредоносный объект как часть своей логики. Достаточно специально подготовленного HTTP-запроса — и код на сервере окажется под контролем не того, кто его писал.
Это не проблема конкретного фреймворка. Под удар попадает любой проект, где используются RSC: Next.js, Remix (с RSC-вставками), любые кастомные серверные интеграции, экспериментальные рантаймы, кастомные бандлы — неважно. Если у вас есть React Server Components, риск реальный.
Уязвимы версии пакетов
Официальное описание: https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
Next.js упоминают чаще всего просто потому, что он массово использует RSC «из коробки», и поэтому количество уязвимых приложений там особенно велико. Но это не его эксклюзивная проблема — это дыра именно в React.
Патчи уже вышли: React закрыл её в версиях 19.0.1, 19.1.2, 19.2.1.
Если у вас Next.js, то актуальные безопасные релизы: 15.0.5+ и 16.0.7
(детали: https://nextjs.org/blog/CVE-2025-66478)
Суть в том, что если ваш сервер хоть как-то отдаёт RSC-ответы и принимает RSC-запросы, обновиться нужно обязательно. Если серверных компонентов нет — пофигу.
Кстати, вот и технический разбор как проблемы, так и патча: https://www.ox.security/blog/rce-in-react-server-components/
#react #rsc #next
В React обнаружили критическую уязвимость в механизме серверных компонентов (React Server Components). Из-за ошибки в том, как React разбирает входящие данные, сервер может попытаться выполнить вредоносный объект как часть своей логики. Достаточно специально подготовленного HTTP-запроса — и код на сервере окажется под контролем не того, кто его писал.
Это не проблема конкретного фреймворка. Под удар попадает любой проект, где используются RSC: Next.js, Remix (с RSC-вставками), любые кастомные серверные интеграции, экспериментальные рантаймы, кастомные бандлы — неважно. Если у вас есть React Server Components, риск реальный.
Уязвимы версии пакетов
react-server-dom-* — 19.0.0, 19.1.0, 19.1.1, 19.2.0.Официальное описание: https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
Next.js упоминают чаще всего просто потому, что он массово использует RSC «из коробки», и поэтому количество уязвимых приложений там особенно велико. Но это не его эксклюзивная проблема — это дыра именно в React.
Патчи уже вышли: React закрыл её в версиях 19.0.1, 19.1.2, 19.2.1.
Если у вас Next.js, то актуальные безопасные релизы: 15.0.5+ и 16.0.7
(детали: https://nextjs.org/blog/CVE-2025-66478)
Суть в том, что если ваш сервер хоть как-то отдаёт RSC-ответы и принимает RSC-запросы, обновиться нужно обязательно. Если серверных компонентов нет — пофигу.
Кстати, вот и технический разбор как проблемы, так и патча: https://www.ox.security/blog/rce-in-react-server-components/
#react #rsc #next
🫡17❤4👍3🤡1
Media is too big
VIEW IN TELEGRAM
#статья дня
Зачем писать код, если можно сгенерировать, правда? Такие нынче правила игры. Но нужно идти дальше.
Зачем писать код, если можно украсть? Особенно, когда сам в руки идёт. Ведь если даже генерировать что-то, нужно, как минимум, учитывать требования по работе, дизайну... никто не отменял понимание сути задачи.
Так вот, сегодня на поветске дня — как украсть любой React-компонент!
И в этом нам поможет React DevTools, любая сносная LLM-ка и вот эта инструкция: https://fant.io/react/
TL;DR
React-приложение хранится не только в DOM-представлении, но и в виде React Fiber — внутреннего дерева (тот самый виртуальный DOM), где видно, какой компонент и с какими пропсами создал разметку.
Все экземпляры одного компонента ссылаются на один и тот же т. н.
Эти примеры вместе с минифицированным кодом компонента скармливаются LLM, которая восстанавливает чистый React. Дальше идёт проверка: компонент рендерится с теми же пропсами, HTML сравнивается с оригиналом, а расхождения отправляются обратно модели. Компоненты собираются снизу вверх, от простых к составным. Анимации и сложные состояния чуток могут замедлить процесс, но для статичного UI он работает прям хорошо.
Дивный новый мир. А чтобы понимать внутренности Fiber, можно использовать инструмент со странным названием bippy: https://github.com/aidenybai/bippy, когда, что и почему отрендерилось.
#react
Зачем писать код, если можно сгенерировать, правда? Такие нынче правила игры. Но нужно идти дальше.
Зачем писать код, если можно украсть? Особенно, когда сам в руки идёт. Ведь если даже генерировать что-то, нужно, как минимум, учитывать требования по работе, дизайну... никто не отменял понимание сути задачи.
Так вот, сегодня на поветске дня — как украсть любой React-компонент!
И в этом нам поможет React DevTools, любая сносная LLM-ка и вот эта инструкция: https://fant.io/react/
TL;DR
React-приложение хранится не только в DOM-представлении, но и в виде React Fiber — внутреннего дерева (тот самый виртуальный DOM), где видно, какой компонент и с какими пропсами создал разметку.
Все экземпляры одного компонента ссылаются на один и тот же т. н.
type, поэтому можно сгруппировать их и собрать реальные примеры прямо из продакшена.Эти примеры вместе с минифицированным кодом компонента скармливаются LLM, которая восстанавливает чистый React. Дальше идёт проверка: компонент рендерится с теми же пропсами, HTML сравнивается с оригиналом, а расхождения отправляются обратно модели. Компоненты собираются снизу вверх, от простых к составным. Анимации и сложные состояния чуток могут замедлить процесс, но для статичного UI он работает прям хорошо.
Дивный новый мир. А чтобы понимать внутренности Fiber, можно использовать инструмент со странным названием bippy: https://github.com/aidenybai/bippy, когда, что и почему отрендерилось.
#react
👍19
#такое дня
Я уже как-то участвовал в нескольких спорах на тему того, что TUI — text-based ui interface — это не больше чем фишечка, такой себе ретрофутуризм.
Ведь каждому очень хочется себя почувствовать хакером из фильмов, если уж до интерфейсов Джарвиса из Железного Человека мы пока не доросли.
Впрочем, как мне справедливо заметили: «А минусы будут?», — да может и нет их...
Но что бы вы думали, взорвавший популярность TUI в последние пару лет Claude Code будет написан на условном C или Python?
Наверное, как сорок лет назад Vim, Emacs и среды Borland Turbo? Ну или ncurses на худой конец там, ведь проблема вывода текста кажется давно решённой?
Нет, там React :) Они рендерят сцену целиком, а потом процессят вьюхи чтобы вывести их текстом, предварительно сравнивая с предыдущим рендера.
Зачем? Да никто не знает, захотелось парням, кто мы такие, чтобы их судить.
Просто экран клода так и будет продолжать мерцать. Обещают, что чуть поменьше, чем раньше. Ведь 16ms на фрейм им теперь хватает с трудом.
Выводов не будет, нет никаких сил. Просто по ссылкам в посте пройдите, там достаточно интересно.
#claude #react
Я уже как-то участвовал в нескольких спорах на тему того, что TUI — text-based ui interface — это не больше чем фишечка, такой себе ретрофутуризм.
Ведь каждому очень хочется себя почувствовать хакером из фильмов, если уж до интерфейсов Джарвиса из Железного Человека мы пока не доросли.
Впрочем, как мне справедливо заметили: «А минусы будут?», — да может и нет их...
Но что бы вы думали, взорвавший популярность TUI в последние пару лет Claude Code будет написан на условном C или Python?
Наверное, как сорок лет назад Vim, Emacs и среды Borland Turbo? Ну или ncurses на худой конец там, ведь проблема вывода текста кажется давно решённой?
Нет, там React :) Они рендерят сцену целиком, а потом процессят вьюхи чтобы вывести их текстом, предварительно сравнивая с предыдущим рендера.
Зачем? Да никто не знает, захотелось парням, кто мы такие, чтобы их судить.
Просто экран клода так и будет продолжать мерцать. Обещают, что чуть поменьше, чем раньше. Ведь 16ms на фрейм им теперь хватает с трудом.
Выводов не будет, нет никаких сил. Просто по ссылкам в посте пройдите, там достаточно интересно.
#claude #react
🤡13❤2👍2
#такое дня
Люди в LinkedIn, конечно, странные. Удивительно, что useEffect и use ничему его не научили в продажах. Но не суть.
А суть в том, что ребята из React, конечно, как продолжали вносить смуту и вытаскивать наружу внутренние особенности реализации, так и продолжают. И никакие You Might Not Need an Effect тут уже не помогут.
Но вообще, конечно, просто смешная картинка. Ведь очевидно, что нужно использоватьEffector React Query.
#react #thoughts
Люди в LinkedIn, конечно, странные. Удивительно, что useEffect и use ничему его не научили в продажах. Но не суть.
А суть в том, что ребята из React, конечно, как продолжали вносить смуту и вытаскивать наружу внутренние особенности реализации, так и продолжают. И никакие You Might Not Need an Effect тут уже не помогут.
Но вообще, конечно, просто смешная картинка. Ведь очевидно, что нужно использовать
#react #thoughts
👍10❤1🫡1
#заметка дня
Иногда стоит выкладывать рекламу, чтобы просто увидеть, что вы живы, котаны. На посты такого количества реакций никогда нет.
А тема сегодняшней заметки — очередная статья на тему «Нам не нужен useEffect»: вот тут.
В чём же проблема таких статей? Да на самом деле проблемы-то особой и нет, есть некоторая недосказанность.
И недосказанность эта связана с тем, что ВСЕ ваши прекрасные библиотеки управления состоянием, анимацией, загрузкой данных и кешем — будут использовать useEffect внутри себя. И говорить, что вы отказываетесь от useEffect — не очень верно.
Что верно, так это то, что их имплементация будет просто намного лучше протестирована. Ну, возможно.
Тем не менее, самый любимый пример, когда отказ от useEffect действительно имеет смысл — на иллюстрации.
Суть проста: если ваше действие требует полной перезагрузки логики, перерисовки компонента — так перерисуйте, блин, компонент, а не пытайтесь через useEffect чота там стартануть.
Продублирую текстом:
Это настолько чисто, элегантно и понятно — что удивляешься, почему это не стало общим паттерном.
Впрочем, дело за вами, котаны.
#react #useeffect #article
Иногда стоит выкладывать рекламу, чтобы просто увидеть, что вы живы, котаны. На посты такого количества реакций никогда нет.
А тема сегодняшней заметки — очередная статья на тему «Нам не нужен useEffect»: вот тут.
В чём же проблема таких статей? Да на самом деле проблемы-то особой и нет, есть некоторая недосказанность.
И недосказанность эта связана с тем, что ВСЕ ваши прекрасные библиотеки управления состоянием, анимацией, загрузкой данных и кешем — будут использовать useEffect внутри себя. И говорить, что вы отказываетесь от useEffect — не очень верно.
Что верно, так это то, что их имплементация будет просто намного лучше протестирована. Ну, возможно.
Тем не менее, самый любимый пример, когда отказ от useEffect действительно имеет смысл — на иллюстрации.
Суть проста: если ваше действие требует полной перезагрузки логики, перерисовки компонента — так перерисуйте, блин, компонент, а не пытайтесь через useEffect чота там стартануть.
Продублирую текстом:
// ❌ BAD: Effect attempts to emulate remount behavior
function VideoPlayer({ videoId }) {
useEffect(() => {
loadVideo(videoId);
}, [videoId]);
}
// ✅ GOOD: key forces clean remount
function VideoPlayer({ videoId }) {
useMountEffect(() => {
loadVideo(videoId);
});
}
function VideoPlayerWrapper({ videoId }) {
return <VideoPlayer key={videoId} videoId={videoId} />;
}
Это настолько чисто, элегантно и понятно — что удивляешься, почему это не стало общим паттерном.
Впрочем, дело за вами, котаны.
#react #useeffect #article
1🫡5👍4👎3❤2