Заметки про React – Telegram
Заметки про React
3.78K subscribers
34 photos
8 videos
485 links
Короткие заметки про React.js, TypeScript и все что с ним связано
Download Telegram
Какой test runner используете на проекте для юнит и интеграционного тестирования?
Anonymous Poll
75%
Jest
5%
Mocha
3%
Ava
2%
Jasmine
6%
Другое
20%
Не пишет тесты
Какие библиотеки для тестирования используете на проекте?
Anonymous Poll
54%
Testing Library
15%
Enzyme
30%
Cypress
11%
Playwright
10%
Selenium
13%
Puppeteer
15%
Другое
👍2
Условные выражения в JSX

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

- Рендеринг по числовому условию. Конструкция вида {gallery.length && <Gallery slides={gallery}>} может отрендерить в DOM число 0. Если gallery.length будет равен 0, то оно как falsy значение будет сразу возвращено из конструкции &&. Чтобы исправить проблему, можно использовать тернарный оператор: {gallery.length ? <Gallery slides={gallery} /> : null}.

- Условное И (&&) имеет больший приоритет, поэтому в конструкциях где имеются И (&&) и ИЛИ (||) используйте скобки для определения приоритета. Например: {cond1 || cond2 && <JSX />} тоже самое что и {cond1 || (cond2 && <JSX />)}, поэтому пишите явно {(cond1 || cond2) && <JSX />}.

- Не зацикливайтесь на тернарных операторах. Если есть вложенные тернарные операторы, то это плохой знак. Вместо вложенных тернарных операторов попробуйте использовать логическое И (&&) или функцию с if/else:

{isEmoji
? <EmojiButton />
: isCoupon
? <CouponButton />
: isLoaded && <ShareButton />}

Код выше можно заменить на функцию:

const getButton = () => {
if (isEmoji) return <EmojiButton />;
if (isCoupon) return <CouponButton />;
return isLoaded ? <ShareButton /> : null;
};

- Будьте аккуратны с props.children в условиях. В props.children может быть пустой массив, фрагмент, одиночный элемент. Поэтому условие {props.children && <div>{props.children}</div>} может привести к багам.

- Одинаковые элементы будут обновляться. Например, код {hasItem ? <Item id={1} /> : <Item id={2} />} будет эквивалентен коду <Item id={hasItem ? 1 : 2} />. Это значит, что при изменении hasItem компонент Item не будет размонтироваться и монтироваться заново, вместо этого будет обновление пропсов.

https://thoughtspile.github.io/2022/01/17/jsx-conditionals/
👍15
React server components под капотом

Чан Ву рассказал про внутреннее устройство React server components (RSC) — "How React server components work: an in-depth guide".

Серверные компоненты — это экспериментальный тип React-компонентов, которые не попадают в клиентский бандл и позволяют бесшовно выносить на сервер часть логики приложения. Результатом выполнения серверных компонентов является представление дерева React-компонентов в формате, подходящем для стриминга. В статье подробно разбирается принцип работы RSC, их ограничения и внутреннее устройство.

Статья хорошая. Рекомендую почитать всем, кто хочет разобраться в устройстве серверных компонентов.

#react #internals

https://blog.plasmic.app/posts/how-react-server-components-work/
👍3
Исправление ошибок гидратации

Бен Илегбоду рассказывает, как исправить проблемы гидратации в React приложениях.

При различиях рендера на сервере и клиенте, React сообщает об этом, выдавая предупреждение в консоль. Если есть различия в атрибутах элемента, то при гидратации React оставит текущие значения атрибутов, полученных от сервера. Это значит, что UI окажется устаревшим. Например, такая проблема может возникнуть с именами классов у элементов, если они генерируются по определенному условию.

Один из способов решения подобных проблем – использование эффектов, о котором подробно рассказал Бен Илегбод в своей статье.

https://www.benmvp.com/blog/handling-react-server-mismatch-error/
👍5
Проблемы в типизации children

Рассмотрим пример компонента:

const Card: React.FC = props => { ... }

export default function App() {
const randomObject = {};
return (
<div className="App">
<Card>{randomObject}</Card>
</div>
);
}

Со стороны TypeScript в данном коде нет ошибок, компонент скомпилируется. Но при запуске приложения будет ошибка со стороны React: Objects are not valid as a React child (found: object with keys {}).
Проблема в том, что неверно написаны типы для React.ReactNode. Если посмотреть в исходники типов, то можно увидеть, что ReactNode расширяется от ReactFragment, который разрешает использование объекта {}.

interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

При разработке компонентов, которые принимают children, стоит учитывать ошибку в типах React. Вариант решения проблемы – создать свой тип ReactNode, который не допускает использование объекта.

https://fettblog.eu/react-types-for-children-are-broken/
👍8
Лучшие практики React Testing Library

Бен Илегбоду делится лучшими практиками при работе с библиотекой для тестирования Testing Library. Кратко о них:

- Используйте user-event вместо fireEvent для взаимодействия с элементами в компоненте. Библиотека Testing Library экспортирует fireEvent, но её API более низкоуровневое. Гораздо проще и читабельнее будет использование user-event.

- Избегайте прямых запросов в DOM. Вместо querySelector используйте запросы получения элементов в зависимости от их роли, содержимого текста, лейбла и т.д.

- Используйте screen вместо деструктуризации render. Эта практика избавит от постоянного изменения объекта деструктуризации по мере добавления или удаления нужных нам запросов.

- Правильно используйте waitFor. Не кладите в колбек waitFor вызовы функций сайд-эффектов, например, клик по кнопке или ввод текста. Внутри waitFor должно быть только утверждение (expect). Связано это с тем, что waitFor вызывает функцию колбека несколько раз, пока утверждение внутри него не станет верным или закончится время на проверку.

Большинство случаев поддержки лучших практик можно добиться установкой правил ESLint для Testing Library, например, eslint-plugin-testing-library.

https://www.benmvp.com/blog/react-testing-library-best-practices/
👍7
Новая документация React

React запустил бету версию сайта документации beta.reactjs.org. Пока что она в процессе наполнения и не все разделы сайта готовы. Но уже сейчас видно, чем новая документация будет отличаться от старой: будет больше интерактивных примеров, добавятся задачи на понимание принципов работы React. Также во всех примерах и объяснениях будут использоваться хуки, а не классы.

https://beta.reactjs.org/
👍16👎1
Тестирование React компонентов с помощью Testing Library

Вводный гайд как тестировать компоненты с помощью библиотеки Testing Library. Автор покрывает основные сценарии тестирования, включая моки fetch запросов, получение элементов по роли и снапшотное тестирование.
Хорошая статья для тех, кто еще не знаком с Testing Library и хочет научиться писать на нем тесты.

https://dev.to/ohdylan/react-component-testing-54ie
👍5
Кастомные хуки и производительность приложения

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

Например, если есть компонент, выполняющий “тяжелые” вычисления и в него нужно добавить кастомный хук, то лучше этот хук добавить в дочернем компоненте. С таким подходом, при работе с хуком будут происходить ререндеры в дочернем компоненте, не влияя на “тяжелый” родительский компонент.

https://www.developerway.com/posts/why-custom-react-hooks-could-destroy-your-app-performance
👍6
Лучшие практики React

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

- Поддержка кода. В начальной стадии проекта нет проблем с поддержкой. Но с ростом количества требований проект становится все больше. Компоненты становятся сложнее и менее поддерживаемыми.

- Масштабируемость проекта. При разработке компонентов и структуры проекта нужно держать в голове идею о том, как проект будет масштабироваться. Следуя этой идее вы с меньшей вероятностью столкнетесь с беспорядком в коде, который потребует серьезного рефакторинга.

- Уверенное понимание React. Проблема в том, что разработчики плохо понимают как работает React под капотом. Это может привести к багам и проблемам с производительностью приложения.


В статье даны как архитектурные, так и практические советы по написанию кода для начинающих разработчиков. Разберем кратко часть из них:

- Создайте хорошую структуру проекта. Организация файлов и папок в проекте влияет на удобство поддержки и масштабируемости.

- Поддерживайте порядок импортов. Разделяйте импорты по уровням, например, сначала внешние модули, потом внутренние модули. Управлять порядком импортов можно с помощью линтера.

- Изучайте разные паттерны компонентов. Например, использование compound components позволяет избавиться от проп дриллинга.

- Используйте TypeScript. Статическая типизация в крупных проектах будет большим плюсом.

- Используйте lazy loading / code splitting. Уменьшение размера бандла положительно скажется на скорости загрузки сайта.

- Обрабатывайте ошибки. Используйте обертку React Error Boundary, чтобы перехватывать ошибки в компонентах и, например, передавать эти ошибки на сервер в логи.

https://www.freecodecamp.org/news/best-practices-for-react/
👍12
Какую проблему решают веб-фреймворки

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

В качестве основного фреймворка для исследования был выбран React. В дополнение к нему были выбраны три новых фреймворка: SolidJS, Svelte и Lit.

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

На VanillaJS, для реализации в своем приложении паттернов из популярных фреймворков можно использовать уже готовые вещи из веб-платформы. Для декларативного стиля программирования использовать HTML и CSS, а для реактивности использовать CSS каскад.

Часть 1. https://www.smashingmagazine.com/2022/01/web-frameworks-guide-part1/
Часть 2. https://www.smashingmagazine.com/2022/02/web-frameworks-guide-part2/
👍5
Производительные React приложения с помощью Context

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

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

Создание нескольких провайдеров для одной формы – довольно сложно и ухудшает поддержку компонента. Если присмотреться к полученной реализации, то можно увидеть, что мы реализовали свой собственный стейт менеджер. Форма была лишь показательным примером того, как работает контекст и как можно его оптимизировать.

https://www.developerway.com/posts/how-to-write-performant-react-apps-with-context
👍7
Использование глобальной мемоизации в React

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

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

https://thoughtspile.github.io/2022/02/09/react-global-memo/
👍7
Повышаем производительность приложения используя ​​React Profiler

React Profiler появился в 2018, но до сих пор пользуется не слишком большой популярностью. На inDepthDev делается разбор этого инструмента. На примере небольшого приложения происходит поэтапное улучшение его производительности, используя React Profiler.

React Profiler позволяет проанализировать, как много коммитов было сделано и какие компоненты были отрендерены, и сколько времени на это ушло. React Profiler не работает “на лету”, сначала нужно сделать запись сеанса профилирования, а уже потом проводить анализ.

Если понимать как работает React Profiler, то можно добиться серьезного увеличения производительности вашего React приложения.

https://indepth.dev/posts/1497/react-profiler
👍6🔥1
Популярный стек для React

Экосистема React большая, постоянно появляются новые библиотеки и инструменты. Йоханнес Кеттманн собрал наиболее популярный стек для React. В качестве способа подсчета популярности является количество скачиваний библиотеки в npm.

Самые популярные библиотеки React:
- Next.js – фреймворк с серверным рендерингом из коробки.
- Redux – библиотека для управления стейта.
- react-query или Apollo – для получения данных.
- react-hook-form или Formik – управление формами.


Популярные библиотеки для написания тестов:
- Jest – для запуска тестов.
- React Testing Library – написание интеграционных тестов.
- Cypress – написание E2E тестов.
- Storybook – для документации и тестирования компонентов.

#beginner

https://profy.dev/article/react-tech-stack
👍6
CSS анимации используя React

CSS анимации предоставляют декларативное API для анимации DOM элементов. Нужно всего лишь указать параметры анимации и определить keyframes, описывающие поведение в заданных точках. Тем не менее, в приложениях, где используется много анимаций, будет сложно поддерживать большое количество анимаций, написанных в CSS.

В техническом блоге BBC рассказали про декларативный подход к использованию CSS анимаций в React через компоненты-анимации. Такой подход позволяет через композицию объединить несколько анимаций.

<FadeIn duration={2} delay={0}>
<Zoom from={1} to={2} duration={2} delay={2}>
<FadeOut duration={2} delay={4}>
<RedBox />
</FadeOut>
</Zoom>
</FadeIn>

С одной из проблем, с которой столкнулись авторы, является определение нужных переходов, в каждом из которых нужно запускать свою анимацию. Для решения данной проблемы используется библиотека по работе с конечными автоматами xstate.

https://medium.com/bbc-design-engineering/css-animations-as-a-dom-based-animations-framework-d6ef582c033a
👍5
Создаем свой React с рендером и useState за 30 минут

Создать свой React не так сложно, как вам может показаться. По крайней мере минимальную версию, которая будет только рендерить JSX. Основная работа заключается в компиляции JSX и рендере элементов.

В React используется синтаксис JSX. Для компиляции JSX в JavaScript можно выбрать TypeScript или babel. При компиляции выражение <h1>React, what are you?</h1> превратится в React.createElement("h1", null, "React, what are you?").

Функция createElement принимает три параметра: тег, атрибуты и содержимое. В качестве содержимого могут быть другие вложенные элементы. Функция createElement возвращает объект React элемента, рендер которого происходит в ReactDOM.render. ReactDOM.render рекурсивно рендерит всех наследников переданного элемента и добавляет атрибуты к DOM элементу.

https://habr.com/ru/post/652487/
👍7
Griffel – новый CSS-in-JS от Microsoft

Microsoft презентовал свою CSS-in-JS библиотеку для стилизации React приложений. Основные фичи:
- возможность компиляции CSS во время сборки и в runtime
- типизация стилей через csstype
- использование Atomic CSS для переиспользования стилей и предотвращения проблем со специфичностью CSS.

Пример использования:

import { makeStyles } from '@griffel/react';

const useClasses = makeStyles({
button: { color: 'red' },
icon: { paddingLeft: '5px' },
});

function Component() {
const classes = useClasses();

return (
<div>
<button className={classes.button} />
<span className={classes.icon} />
</div>
);
}

При написании стилей поддерживаются псевдоклассы, псевдоэлементы и at-правила. Также в Griffel есть API для создания глобальных стилей, которые не привязаны к компоненту – makeStaticStyles.

https://github.com/microsoft/griffel

Очень интересно наблюдать, как появляются новые CSS-in-JS библиотеки, особенно от таких крупных компаний. Еще в 2019 году Facebook рассказал о своей CSS-in-JS библиотеке – Stylex. Правда она еще до сих пор не появилась на гитхабе.
👍7👎3
Релиз версии Next.js 12.1

Произошел релиз Next.js 12.1 с одной из самых востребованных фич – Incremental Static Regeneration (ISR). ISR позволяет создавать и обновлять статические страницы сайта после сборки проекта. Обновление статической страницы возможно двумя способами. Обновить статическую страницу можно автоматически, спустя заданное количество секунд после последней генерации страницы:

export async function getStaticProps() {
return {
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}

Также возможно ручное обновление страницы. Например, такое пригодится для интернет-магазинов, при изменении цены товара на странице:

// pages/api/revalidate.js
export default async function handler(req, res) {
// Check for secret to confirm this is a valid request
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Invalid token' })
}

try {
await res.unstable_revalidate('/path-to-revalidate')
return res.json({ revalidated: true })
} catch (err) {
// If there was an error, Next.js will continue
// to show the last successfully generated page
return res.status(500).send('Error revalidating')
}
}


Другие изменения в новой версии:
- Улучшена поддержка SWC. Некоторые Babel плагины были портированы на Rust. Включена поддержка styled-components, relay.
- Автоматическая конфигурация Jest.
- Более быстрая минификация, используя SWC. В 7 раз быстрее чем Terser.
- Оптимизация изображений. API по работе с изображениями поддерживает паттерн ISR.
- Работа в сторону поддержки React 18, серверных компонентов и потокового SSR. Была обновлена документация для тех, кто хочет попробовать эти фичи.

https://nextjs.org/blog/next-12-1
👍7
Доступен React 18 RC

Версия React 18 стала доступна в качестве релиз-кандидата. Чтобы установить, нужно использовать @rc тег:

npm install react@rc react-dom@rc
// или
yarn add react@rc react-dom@rc


В React 18 появится новое API для библиотек. Для поддержки конкурентного рендеринга сторонними библиотеками было добавлено следующее API:
- useId – хук для генерации уникального id на клиенте и сервере, поддерживающего гидратацию. Подробнее.
- useSyncExternalStore – хук для работы с внешними хранилищами, позволяющий производить параллельное чтение из источника и синхронную запись. Подробнее.
- useInsertionEffect – хук для вставки стилей в процессе рендера, предназначен для CSS-in-JS библиотек. Подробнее.

Новые изменения в строгом режиме (strict mode). В будущем React планирует поддерживать пользовательский UI, в котором части интерфейса можно будет удалить с сохранением стейта, чтобы потом их можно было восстановить. Например, переключение табов на странице, когда при смене таба нужный компонент будет отображаться сразу с восстановленным состоянием.

Для поддержки такого UI сценария React добавляет новую проверку в development режиме в strict mode. Эта новая проверка будет автоматически демонтировать и повторно монтировать каждый компонент всякий раз, когда компонент монтируется в первый раз, восстанавливая предыдущее состояние при втором монтировании.

Также в React 18 прекращается поддержка браузера Internet Explorer.

https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
👍7