Заметки про React
описание
Короткие заметки про React.js, TypeScript и все что с ним связано
3 501
подписчиков
Охват к подписчикам
88,8%
ERR
Реакции к просмотрам
0,74%
460 на 20 постов
Пересылки к просмотрам
1,24%
773
Постов в день
0,0
всего 20
Где отзываются чаще
доля реакций к просмотрам- 15 апр. 2025 г.TypeScript перепишут на Go Новую версию TypeScript перепишут на Go. Это связано в первую очередь со скоростью работы. TypeScript медленно работает на больших кодовых базах. Особенно это замечается при рефакторинге кода в VS Code, например когда переименовываешь переменную или ищешь все ссылки на интерфейс. По заверениям Андерса Хейлсберга, при использовании компилятора на Go, скорость работы команды tsc увеличивается в 10 раз. Например, запуск tsc на кодовой базе Playwright вместо 11 секунд занимает 1.1 секунду. Также использование компилятора на Go значительно ускоряет работу редактора VS Code. По замерам автора, скорость загрузки проекта выросла в 8 раз. Текущая версия TypeScript 5.8. Следующая мажорная версия TypeScript 6 останется написана на TS, но появятся пометки deprecated и критические изменения для поддержки 7ой версии. Когда в кодовой базе на Go станет достаточно функционала, который покрывает версию на TS, то выпустят TypeScript 7 на Go. https://devblogs.microsoft.com/typescript/typescript-native-port/1,38%
- 27 мая 2025 г.Управление фокусом в React с помощью flushSync Установить фокус на инпуте сразу в React может оказаться не так просто, как кажется. При изменении стейта, React не сразу ре-рендерит компонент, а вместо этого он складывает в очередь все изменения состояний и выполняет их разом после завершения работы обработчика событий. Из-за такого поведения могут возникнуть непредвиденные ситуации, например: function MyComponent() { const inputRef = useRef<HTMLInputElement>(null) const [show, setShow] = useState(false) return ( <div> <button onClick={() => { setShow(true) inputRef.current?.focus() // Фокус не будет работать }} > Show </button> {show ? <input ref={inputRef} /> : null} </div> ) } В примере выше фокс на инпуте не появится, из-за того что изменение стейта setShow сработает только по завершению работы обработчика события onClick. Для решения проблемы используйте функцию flushSync, которая синхронно выполняет изменение стейта в переданном колбеке. По завершению работы flushSync DOM будет обновлен и inputRef.current?.focus() сработает. Обновленный пример обработчика: … <button onClick={() => { flushSync(() => { setShow(true) }) inputRef.current?.focus() }} > … https://www.epicreact.dev/mastering-focus-management-in-react-with-flush-sync-f5b381,21%
- 22 апр. 2025 г.Показ тостов через React Server Components В блоге Build UI показали пример, как, используя React Server Components, показывать всплывающие сообщения (тосты) на клиенте. В примере используются серверные функции, куки и useOptimistic. По итогу, чтобы вызвать тост на клиенте, достаточно в любой серверной функции сделать вызов функции toast, пример: "use server"; export async function save() { await toast("Blog post successfully saved!"); } Функция toast выглядит следующим образом: "use server"; import { cookies } from "next/headers"; async function toast(message: string) { const cookieStore = await cookies(); const id = crypto.randomUUID(); cookieStore.set(`toast-${id}`, message, { path: "/", maxAge: 60 * 60 * 24, // 1 day }); } Используется случайный ID в названии куки для того, чтобы гарантировать уникальность названия куки. Чтобы отображать куки на клиенте, надо считать куки, отфильтровать по префиксу toast: import { cookies } from "next/headers"; import { ClientToasts } from "./client-toasts"; export async function Toaster() { const cookieStore = await cookies(); const toasts = cookieStore .getAll() .filter((cookie) => cookie.name.startsWith("toast-") && cookie.value) .map((cookie) => ({ id: cookie.name, message: cookie.value, dismiss: async () => { "use server"; const cookieStore = await cookies(); cookieStore.delete(cookie.name); }, })); return <ClientToasts toasts={toasts} />; } Как видно из кода выше, для удаления куки используется серверный API Next.js. Почему не использовать браузерное API для удаления? По мнению автора, работать с браузерным document.cookie менее приятно, чем с API от Next.js. В ClientToasts автор использует хук useOptimistic, чтобы реализовать немедленное удаление тоста с экрана пользователя и отправить запрос на удаление куки на сервер: export function ClientToasts({ toasts }: { toasts: Toast[] }) { const [optimisticToasts, remove] = useOptimistic(toasts, (current, id) => current.filter((toast) => toast.id !== id), ); const localToasts = optimisticToasts.map((toast) => ({ ...toast, dismiss: async () => { remove(toast.id); await toast.dismiss(); }, })); return … } Одна из особенностей подхода хранения тостов в куках заключается в том, что тосты будут отображаться при редиректах, в новых вкладках и перезагрузках страницы. https://buildui.com/posts/toast-messages-in-react-server-components1,16%
- 15 мая 2025 г.TanStack DB TanStack представила новую библиотеку – TanStack DB – реактивный клиентский стор, с возможностью синка API запросов. Библиотека работает поверх TanStack Query и расширяет его функционал. Разработчики обещают быструю скорость работы библиотеки, даже на больших объемах данных. Библиотека предлагает fine-grained реактивность, возможность нормализации данных и примитивы транзакций. Примеры использования: Синк данных коллекции с API: import { createQueryCollection } from "@tanstack/db-collections" const todoCollection = createQueryCollection<Todo>({ queryKey: ["todos"], queryFn: async () => fetch("/api/todos"), getId: (item) => item.id, schema: todoSchema, // любая схема }) Использование live query и фильтрации: import { useLiveQuery } from "@tanstack/react-db" const Todos = () => { const { data: todos } = useLiveQuery((query) => query.from({ todoCollection }).where("@completed", "=", false) ) return <List items={todos} /> } Использование транзакций и оптимистичных изменений на клиенте: import { useOptimisticMutation } from "@tanstack/react-db" const AddTodo = () => { const addTodo = useOptimisticMutation({ mutationFn: async ({ transaction }) => { const { collection, modified: newTodo } = transaction.mutations[0]! await api.todos.create(newTodo) await collection.invalidate() }, }) return ( <Button onClick={() => addTodo.mutate(() => todoCollection.insert({ id: uuid(), text: "🔥 Make app faster", completed: false, }) ) } /> ) } https://github.com/TanStack/db1,09%
- 28 янв. 2025 г.react-scan для поиска проблем производительности Вышла библиотека react-scan для поиска проблем производительности и устранения медленного рендера приложения. В отличии от других похожих библиотек, для установки react-scan не требуется изменений в коде приложения, достаточно вставить тег <script> или можно установить как модуль. Библиотека react-scan выделяет только те компоненты, которые надо оптимизировать. Разработчики обещают в будущем выпустить расширение для браузера. https://github.com/aidenybai/react-scan1,04%
- 29 мая 2025 г.Анонс TypeScript Native Вышла превью версия TypeScript написанная на Go. Ее можно установить через npm: npm install -D @typescript/native-preview Этот пакет предоставляет команду tsgo – он работает аналогично команде tsc. Со временем команда tsgo переименуется в tsc и переедет в пакет typescript. Сейчас команды разделены для удобства тестирования. Помимо команды tsgo появилось расширение в VS Code для использования TypeScript Language Service на Go в редакторе – “TypeScript (Native Preview)”. С этим расширением должны ускориться такие функции, как go-to-definition, автокомоплит подсказок, вывод ошибок, показ всплывающих подсказок и другое. https://devblogs.microsoft.com/typescript/announcing-typescript-native-previews/1,03%
- 4 июн. 2025 г.Почему Error Boundary, а не просто try/catch для компонентов В React нельзя использовать try/catch чтобы отловить ошибки рендера компонента. Это связано с тем, что React не вызывает функцию Calculator когда он создает элемент, он лишь создает описание того что надо отрендерить. const element = ( <div> <h1>Calculator</h1> <Calculator left={1} operator="+" right={2} /> <Calculator left={1} operator="-" right={2} /> </div> ) Поэтому если обернуть объявление выше в try/catch можно получить только ошибки во время создания этих элементов, а не ошибки рендера. Реальные ошибки происходят внутри компонента, во время рендера, эффектов и обработчиков ошибок. function Calculator(props) { try { // ...render logic } catch (error) { return <div>Ошибка!</div> } } По примеру выше можно обернуть в try/catch тело компонента, но это лишь обработает ошибки на уровне данного компонента. Для обработки ошибок внутри компонента используют Error Boundary. Рекомендуется использовать библиотеку react-error-boundary, которая предоставляет готовый компонент ErrorBoundary и хук useErrorBoundary для обработки ошибок в асинхронных колбеках, эффектах, обработчиках ошибок. Пример использования хука: import { useErrorBoundary } from 'react-error-boundary' function MyComponent() { const { showBoundary } = useErrorBoundary() async function handleClick() { try { await doSomethingAsync() } catch (error) { showBoundary(error) } } return <button onClick={handleClick}>Do something</button> } https://www.epicreact.dev/why-react-error-boundaries-arent-just-try-catch-for-components-i6e2l0,90%
- 18 февр. 2025 г.State of React 2024 Вышла статистика по React за 2024. В ней собрана информация о наиболее/наименее популярных фичах в React, библиотеках, инструментах. Вот наиболее интересные факты: ⭐️ forwardRef — самый нелюбимый API в React, который, кстати, в 19 версии стал устаревшим и можно прокидывать ref напрямую в пропсы. ⭐️ React Compiler и React Server Components наиболее популярные из новых фич React, при этом RSC наиболее сложная и непонятная. ⭐️ Taint API – самый неизвестный API, но это и понятно, т.к. он является экспериментальным. ⭐️ Zod – наиболее популярная библиотека для валидации, а Jest – для тестирования. ⭐️ Next.js, TanStack Query, Redux, Axios – наиболее популярные библиотеки, а TanStack Query и Zustand – самые любимые. https://2024.stateofreact.com/ru-RU/0,81%
- 24 июн. 2025 г.Реактивность – это легко Стандартный useContext заставляет обновляться все компоненты-потребители, даже если им не нужна изменившаяся часть состояния. Это приводит к лишним ре-рендерам, особенно в больших компонентах вроде таблиц или списков. Автор статьи столкнулся с этим в MUI X Data Grid: клик по одной ячейке вызывал ре-рендер всех остальных. Решение — точечная подписка через селекторы Вместо того, чтобы хранить состояние в useState и передавать его через Context, можно использовать внешний Store и специальный хук useSelector. Идея проста: 🔴 Store — это обычный класс, который хранит состояние, умеет подписывать на обновления (subscribe) и уведомлять подписчиков, когда данные изменились (update). Он живёт вне рендера React. 🔴 useSelector(store, selectorFn) — кастомный хук, который принимает store и функцию-селектор. Селектор — это функция, которая из всего объекта состояния достает только нужный компонентa фрагмент данных (например, `state => state.focus === index`). Хук подписывается на store и вызывает локальный ре-рендер только тогда, когда возвращаемое селектором значение изменилось. Пример кода: const Context = createContext(); export function Grid() { const [store] = useState(() => new Store({ focus: 0 })); return ( <Context.Provider value={store}> {Array.from({ length: 50 }).map((_, i) => ( <Cell index={i} /> ))} </Context.Provider> ); } const selectors = { isFocus: (state, index) => state.focus === index, }; function Cell({ index }) { const store = useContext(Context); const focus = useSelector(store, selectors.isFocus, index); return ( <button ref={ref} onClick={() => store.update({ ...store.state, focus: index })} className={clsx({ focus })} > {index} </button> ); }; Такой подход позволяет обновлять только те компоненты, чьи данные действительно изменились, и часто избавляет от необходимости оборачивать всё в React.memo. https://romgrk.com/posts/reactivity-is-easy/0,76%
- 4 февр. 2025 г.Create React App устарел Create React App был одним из основных инструментов для старта приложения в 2017-2021 году. Сейчас он официально устарел и в Readme рекомендуют перейти на другой React фреймворк. Если вы захотите использовать CRA с React 19, то столкнетесь с множеством NPM ошибок при настройке проекта. Это обусловлено сочетанием нескольких факторов. CRA всегда пытается установить последнюю версию React по умолчанию, но 19 версии не указана в шаблонах пакета. Шаблон по умолчанию использует @testing-library/react@13.0, который зависит от react@18. Это значит, что установка 19 версии приведет к несоответствию версий. https://github.com/facebook/create-react-app/issues/170040,72%
- 17 апр. 2025 г.Кейсы оптимизации React Обзор примеров, показывающих, как пять разных команд разработчиков оптимизировали React. Например, у одной из команд на проекте был плохой показатель метрики INP, которая отслеживает скорость отклика сайта. Хорошим считается отклик менее 200мс, на проекте был отклик 380мс. Какие были найдены причины: - Большой бандл. Первоначально грузился большой бандл с кодом, который не был нужен. Помог code splitting. - Определенные колбеки у обработчиков событий вызывались слишком часто, из-за чего блокировался основной поток браузера. Помог debounce на скролл и resize, а также делегирование событий. - Ре-рендерелись больше компонентов чем нужно при изменении стейта. Помогло оборачивание компонентов в React.memo() и использование useMemo для дорогих вычислений. - Долгий рендеринг компонентов. Помогло обновление до React 18. Основным преимуществом этого обновления стал параллельный рендеринг, поскольку высокоприоритетные задачи, такие как пользовательский клик, могут прерывать рендеринг. Это обновление улучшило метрику INP на 46% на десктопе. Помимо это помогли следующие исправления для улучшения производительности рендеринга: - Разбиение сложных хуков на более мелкие. На графике перфоманса было видно, что сложные хуки вызываются несколько раз и перерисовывают компонент без необходимости. - Замена React Router на window.location там, где это возможно. - Улучшение мемоизации Redux селекторов. https://largeapps.dev/case-studies/advanced/0,71%
- 21 янв. 2025 г.Основы доступности, которые должен знать каждый фронтенд-разработчик Мартин Холс в своем блоге рассказал о ключевых принципах доступности, которые должен знать каждый фронтенд-разработчик при разработке компонентов. Часть того, о чем пишет автор: 🔴 Семантический HTML. Используйте правильные элементы для интерактивности и нативные элементы. Если нужно показать кнопку, то используйте <button>, а для ссылок <a>. Не надо вместо этого использовать onClick на div элементе. Такие нативные элементы как <select>, <input> и <textarea> доступны из коробки, старайтесь использовать их. Но если запланируете делать кастомный элемент на подобие <select>, то лучше использовать готовые решения, например, react-select. 🔴 Формы. Каждое поле формы должно быть внутри элемента <form> с onSubmit и кнопкой отправки. Это позволяет браузерам определять связанные поля формы и, например, на мобильных устройствах позволяет переключаться между полями без закрытия клавиатуры. 🔴 Навигация с помощью клавиатуры. Проверьте что в приложении можно переключаться между элементами по нажатию Tab и работает Enter. Используйте CSS индикаторы фокуса :focus-visible и :focus. 🔴 Модалки. Сделать их доступными может быть не просто. Важно при открытии модалки переключать фокус внутри него, а при закрытии возвращать фокус на кнопку открытия модалки. 🔴 Стилизация. Улучшайте доступность интерфейсов через стилизацию, например: - проверьте, что ссылки выглядят как ссылки, а кнопки как кнопки; - сделайте отчетливые состояния элемента при наведении, активном и выключенном состоянии; - используйте достаточный контраст цветов для различения элементов; - поддержите пользовательские размеры шрифтов и зуминг; - поддержите настройку отключения анимации; https://martijnhols.nl/blog/accessibility-essentials-every-front-end-developer-should-know0,69%