Заметки про React – Telegram
Заметки про React
3.78K subscribers
34 photos
8 videos
485 links
Короткие заметки про React.js, TypeScript и все что с ним связано
Download Telegram
Архитектура React Query

Доминик Дорфмайстер подготовил верхнеуровневое устройство библиотеки React Query. Из-за внутреннего устройства библиотеки её легко адаптировать под любой фреймворк. Адаптеры для React и Solid занимают не больше 100 строк кода.

Все начинается с QueryClient, который используется во всем приложении. Это контейнер для кэша QueryCache и MutationCache. Кэш хранит запросы – объекты Query. Объект Query хранит в себе информацию о запросе, выполняет сам запрос, делает отмену и дедупликацию.

При использовании хука useQuery создается Observer. Это промежуточный объект между Query и компонентом React. Он информирует компонент о необходимости ре-рендера при изменении состояния запроса Query.

https://tkdodo.eu/blog/inside-react-query
👍11
Nextra 2.0

Nextra – это инструмент, облегчающий разработку документации сайта, основанный на Next.js и разрабатываемый командой Vercel.

Новый релиз 2.0 включает в себя редизайн и новые фичи: MDX 2, поддержка Tailwind, встроенный поиск FlexSearch, i18n, доступность A11Y, подсветка кода.

Использование Next.js позволяет организовать роутинг страниц на основе структуры проекта. Также можно создавать как динамические страницы (SSR), так и генерировать статические страницы.

С помощью Nextra созданы сайты документаций для проектов Turbo, SWR и других проектов Vercel.

https://nextra.site/
👍5
Гексагональная архитектура в React

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

Алекс Кондов рассказал о подходе к разработке приложений на React с применением гексагональной архитектуры. Для доступа к доменной логике в компонентах используются хуки. Хуки – это адаптеры между React и вашим доменным кодом. Под доменным кодом имеются в виду запросы в API, управление пользователем или любой другой бизнес-сущностью. Сама доменная логика может быть реализована с помощью любой удобной парадигмой программирования. В качестве примера можно посмотреть на react-query. Эта библиотека написана с помощью ООП и использует хуки как адаптер к React.

function PostPage({ postId }) {
const { post, error, bookmarkPost, reactToPost } = usePost(postId);

// --snip--
}

function usePost(postId) {
const [post, setPost] = useState(null);
// --snip--

const getPost = () => {
client.getPost(postId).then(setPost).catch(setError)
}

const bookmarkPost = () => {
client.bookmarkPost(postId, userId);
};

useEffect(() => {
getPost()
}, [])

// --snip--

return {
post: mapToDomainObject(post),
bookmarkPost,
// --snip--
};
}


https://alexkondov.com/hexagonal-inspired-architecture-in-react/
👍7👎7
Релиз Vite 4.0

Вышла новая версия Vite 4.0. Основные изменения:

• Используется Rollup 3.
• Новый плагин для сборки @vitejs/plugin-react-swc. Он использует esbuild для сборки приложения и SWC вместо Babel во время разработки.
• Современная сборка по умолчанию нацелена на safari14 вместо safari13. Если нужна поддержка старых браузеров, то используйте @vitejs/plugin-legacy.
• Кодировка сборки по умолчанию utf8.
• Для импорта CSS как строки используйте суффикс ?inline: import stuff from './global.css?inline’.

https://vitejs.dev/blog/announcing-vite4.html
👍5
Плохие практики использования useState

Хук useState используется чаще всего при работе с React. Есть несколько плохих практик при работе с ним, которые приводят к более сложному коду, увеличению количества багов и ухудшению производительности компонента.

Йоханнес Кеттманн в блоге Profy собрал список плохих практик использования useState и предложил к каждому свое решение. Кратко про часть из них:

Избыточный стейт. Стейт, который зависит от другой переменной стейта, скорее всего можно безболезненно заменить на производную переменную. Пример избыточного стейта:

const onChangeFirstName = (event) => {
setFirstName(event.target.value);
setFullName(`${event.target.value} ${lastName}`);
};


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

function DuplicateState({ items }) {
const [selectedItem, setSelectedItem] = useState();
const onClickItem = (item) => {
setSelectedItem(item);
};
// --snip--
}


При изменении пропса items в selectedItem могут оказаться устаревшие данные. Чтобы избежать обращения к устаревшим данным, вместо selectedItem используйте selectedItemId. А selectedItem будет вычисляться по выбранному id из items.

Обновление стейта в useEffect. При обновлении стейта в useEffect происходит дополнительный рендер. Также бывает сложно вызвать эффект в нужное время. Например, эффект вызывается при инициализации компонента. Поэтому старайтесь избегать обновления стейта в useEffect. Кстати, есть интересный доклад про useEffect от Дэвида Хуршиди. В нем он призывает вообще отказаться от useEffect.

https://profy.dev/article/react-usestate-pitfalls
👍11
Оптимизация веб шрифтов в Next.js 13

При загрузке кастомных веб шрифтов на сайте может возникнуть проблема FOUT (Flash Of Unstyled Text) или FOIT (Flash Of Invisible Text). Из-за FOUT и FOIT может произойти сдвиг макета, который сбивает пользователя с толку.

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

При загрузке кастомного веб шрифта стоит обратить внимание на дескрипторы шрифта. В CSS это свойства size-adjust, ascent-override, descent-override и line-gap-override. Они предназначены для настройки характеристик отображения шрифта. Например, два разных веб шрифта с одинаковым размером шрифта могут занимать разное количество места на странице. При настройке CSS дескрипторов запасного шрифта можно добиться схожести размеров на загружаемый кастомный веб шрифт. Вследствие чего можно избежать сдвига макета.

В Next.js 13 появился новый модуль @next/font. Он позволяет использовать локальные и Google Fonts шрифты, не беспокоясь о деталях оптимизации. При использовании Google Fonts этот модуль скачивает шрифт во время сборки и добавляет запасной шрифт, автоматически добавляя настройки CSS дескриптора:

import { Poppins } from "@next/font/google";

const poppins = Poppins({ weight: "600", subsets: ["latin"] });

export default function Title() {
return <h1 className={poppins.className}>The Acme Blog</h1>;
}


https://www.lydiahallie.io/blog/optimizing-webfonts-in-nextjs-13
🔥10👍41
Применение паттерна Стратегия в React

При разработке React приложения бывает проблема, когда одна часть бизнес-логики реализована по частям в нескольких компонентах, хуках и функциях. У этой проблемы есть название “Стрельба дробью” (Shotgun Surgery). Это запах кода, в котором одно изменение затрагивает сразу несколько классов приложения.

Один из вариантов решения этой проблемы – паттерн Стратегия. В блоге dev.to автор Хьюго Та поделился примером использования паттерна Стратегия при разработке компонента.

В качестве примера – карточки с ценами. Если посетитель из определенной страны, то в карточке указывается цена в валюте его страны и возможная скидка. Для реализации такой бизнес-логики автор создал базовый абстрактный класс и имплементировал классы для разных стран.

abstract class PriceStrategy {
protected country: Country = Country.AMERICA;
protected currency: Currency = Currency.USD;
protected discountRatio = 0;

// --snip--
}

class JapanPriceStrategy extends PriceStrategy {
constructor() {
super();
this.country = Country.JAPAN;
this.currency = Currency.YEN;
this.discountRatio = 0.2;
}

// --snip--
}

<PricingCard price={7669} strategy={new JapanPriceStrategy()} />


https://dev.to/itshugo/applying-design-patterns-in-react-strategy-pattern-enn
👎12👍5
Цветовые форматы в CSS

В CSS есть несколько цветовых форматов: хекскод, rgb(), hsl(), lch() и другие. Самые популярные из них - это хекскод и rgb(). А для чего существуют остальные, и нужно ли их использовать?

В блоге Джошуа Комо вышел гайд по цветовым форматам. В нем он разобрал каждый цветовой формат и его применимость.

https://www.joshwcomeau.com/css/color-formats/
👍2
Переименование экспериментального useEvent в useEffectEvent

В репозитории React смержили ПР, в котором переименовали useEvent в useEffectEvent.

Ранее в устаревшем RFC про useEvent показывали пример использования хука: в эффектах и для оптимизации рендера. Теперь хук будет использоваться только в эффектах. По сообщению Дэна Абрамова оптимизация рендеринга будет прорабатываться отдельно.

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

const onHappened = useEffectEvent(() => ...);
useEffect(() => {
onHappened();
}, []);


https://github.com/facebook/react/pull/25881
👍5👎4
GitHub Unwrapped 2022

Команда Remotion создала сайт, который генерирует видео о ваших результатах в Github в 2022 году.

Для получения статистики используется GitHub GraphQL API. Само видео создается с помощью библиотеки Remotion.

https://www.githubunwrapped.com/
👍5
Самые популярные CSS-in-JS библиотеки в 2022 году

Опрос State of CSS выделил CSS-in-JS библиотеки, которые оказались наиболее часто используемыми среди фронтенд-разработчиков за 2022 год.

В тройке самых популярных оказались Styled Components, CSS Modules и Styled JSX. Алекс Ивановс написал по каждой библиотеке из рейтинга краткую информацию, пример использования и основные фичи.

https://stackdiary.com/css-in-js-libraries/
👍3👎3
React Email

Библиотека для создания email шаблонов с помощью React и TypeScript. Содержит набор готовых компонентов без стилей.

При рендере шаблона создается совместимый с популярными почтовыми клиентами HTML код. Также есть dev режим, в котором можно увидеть, как будет выглядеть шаблон при рендере.

Для рендера шаблона используется функция render:

import { MyTemplate } from '../components/MyTemplate';
import { render } from '@react-email/render';

const html = render(<MyTemplate firstName="Jim" />, {
pretty: true,
});


В документации есть пример интеграции с почтовыми провайдерами: Nodemailer, SendGrid, Postmark и AWS SES. На сайте есть примеры готовых шаблонов.

https://react.email/
👍13
React Concurrency под капотом

Наконец-то опубликовался доклад, с которым я выступал осенью на Smashing Conf и performance.​now(). Ловите :) https://3perf.com/talks/react-concurrency/

Внутри — куча картинок про новые перфоманс-фичи React 18:
⚛️ Как именно работает useTransition() (с демкой в девтулзах и просмотром кода из React-а, да)
🧊 Как применять <Suspense>, чтобы ускорить гидрацию, и как его не применять
🫠 Почему Vue.js и Preact отказались реализовывать что-то похожее на React Concurrency

(и другое)
🔥9👍3
Варианты использования React ref callback

В блоге Джулс Блом вышел подробный гайд по вариантам использования ref callback.

Ref callback - это функция, которая передается хост элементу в атрибут ref. React вызывает эту функцию с ссылкой на DOM элемент при монтировании компонента и с null при размонтировании компонента.

Ref callback позволяет выполнять различные действия в момент, когда React прикрепляет или открепляет ref к DOM элементу. Например:
- Выполнить скролл или фокус к элементу при монтировании.
- Узнать DOM свойства при монтировании, например, размер элемента.
- Создание порталов в DOM элемент, созданный React.
- Поделиться DOM элементом с несколькими потребителями.

https://julesblom.com/writing/ref-callback-use-cases
👍83🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
React Wrap Balancer

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

https://github.com/shuding/react-wrap-balancer
🔥13👍4
Обработка ошибок с TypeScript

Для долговечности работы проекта крайне важно отлавливать и обрабатывать ошибки.

В TypeScript при обработке ошибки в try/catch тип ошибки всегда unknown:

try {
// --snip--
} catch (error) {
// error is unknown
}


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

В JavaScript много стандартных типов ошибок, например: ReferenceError, TypeError, SyntaxError. Также можно создавать свои собственные – пользовательские типы ошибок. При создании пользовательского типа ошибки расширяйтесь от стандартного класса Error, чтобы к ошибке прикреплялся стектрейс. Использование пользовательских ошибок позволяет более детально обрабатывать каждую ошибку и по разному реагировать на нее приложению. Пример:

export class ProjectError extends Error {
name: ErrorName;
message: string;
cause: any;

constructor({
name, message, cause
}: {
name: ErrorName;
message: string;
cause?: any
}) {
super();
this.name = name;
this.message = message;
this.cause = cause;
}
}

try {
throw new ProjectError({
name: "CREATE_PROJECT_ERROR",
message: "API Error"
});
} catch (error) {
if (error instanceof ProjectError) {
if (error.name === "CREATE_PROJECT_ERROR") {
toast(error.message);
}
}
}


https://engineering.udacity.com/handling-errors-like-a-pro-in-typenoscript-d7a314ad4991
👍8
Абсолютная абстракция форм в React

Гайд по созданию абстракций для форм от Брендана Аллана. В примерах для работы с формами автор использует react-hook-form, TypeScript и Zod.

Преимущество Zod в том, что он полностью поддерживает TypeScript, также есть утилитарный тип TypeOf для выведения типа из схемы. RHF поддерживает Zod через resolver.

Пример кастомного хука формы:

import { useForm, UseFormProps } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { TypeOf, ZodSchema } from 'zod';

interface UseZodFormProps<Z extends ZodSchema>
extends Exclude<UseFormProps<TypeOf<Z>>, 'resolver'> {
schema: Z;
}

export const useZodForm = <Z extends ZodSchema>({
schema,
...formProps
}: UseZodFormProps<Z>) =>
useForm({
...formProps,
resolver: zodResolver(schema),
});


https://www.brendonovich.dev/blog/the-ultimate-form-abstraction
👍13👎2
Практики композиции функций в React

Композиция функций – мощный способ создания сложной функциональности путем объединения простых и переиспользуемых функций. В контексте React композиция функций позволяет создавать более сложные и переиспользуемые компоненты, что улучшает организацию и структуру кода в больших приложениях.
Филиппо Ривольта в своем блоге поделился практиками композиции функций:

- Используйте HoC для абстракции общей функциональности. Оборачивая в HoC мы можем добавить дополнительное поведение или пропсы, не изменяя оригинальный компонент.
- Объединяйте несколько HoC, используя композицию: compose(withFoo, withBar, withBaz)(Component).
- Один HoC делает только одну работу, используйте кастомные хуки для хранения состояния.
- Используйте техники функционального программирования, например, каррирование.

Пример реализации HoC, который абстрагирует логику получения данных о пользователе:

import { useEffect, useState } from 'react';

function useFetchUsers(url) {
const [users, setUsers] = useState([]);
useEffect(() => {
async function fetchData() {
const res = await fetch(url);
const data = await res.json();
setUsers(data.users);
}
fetchData();
}, [url]);
return users;
}

function withFetchUsers(Component) {
return function WrappedComponent(props) {
const users = useFetchUsers(props.url);
return <Component {...props} users={users} />;
}
}


https://medium.com/@rivoltafilippo/function-composition-in-large-react-applications-best-practices-and-real-world-examples-805aba8d37b1
👍6👎5
Библиотеки для визуализации

Подборка новых библиотек для визуализации данных для React:

visx

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

export default function Bars() {
// --snip--
const yScale = useMemo(
() =>
scaleLinear<number>({
range: [yMax, 0],
round: true,
domain: [0, Math.max(...data.map(getLetterFrequency))],
}),
[yMax],
);

return (
<noscript width={width} height={height}>
<GradientTealBlue id="teal" />
<Group top={verticalMargin / 2}>
{data.map((d) => {
// --snip--
const barHeight = yMax - (yScale(getLetterFrequency(d)) ?? 0);
const barX = xScale(letter);
return (
<Bar
key={`bar-${letter}`}
x={barX}
y={barY}
// --snip--
/>
);
})}
</Group>
</noscript>
);
}



mafs

Библиотека готовых компонентов для интерактивной математики. Позволяет создавать интерактивные и анимированные элементы из математики. Содержит компоненты: система координат, точки, линии, полигоны, круги и т.д.

function LineSegmentExample() {
const point1 = useMovablePoint([-1, -1])
const point2 = useMovablePoint([2, 1])

return (
<Mafs viewBox={{ y: [-1, 1] }}>
<CartesianCoordinates />
<Line.Segment
point1={point1.point}
point2={point2.point}
/>
{point1.element}
{point2.element}
</Mafs>
)
}
👍41
Все что вам нужно знать про конкурентный рендеринг

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

Для того чтобы активировать конкурентный рендеринг, нужно использовать либо переходы – useTransition или просто startTransition, либо отложенные значения – useDeferredValue. Эти API позволяют пометить обновления стейта низким приоритетом. Обновления стейта, которые объявляются вне фич конкурентного рендеринга, помечаются как обновления с высоким приоритетом.

Хенрику Йужи подробно разобрал API конкурентного рендеринга и описал крайние кейсы использования. Например, нужно понимать, что React рендерит в однопоточной среде. И если он начал рендерить компонент, то он будет рендерить его до конца без прерываний. Только по окончании рендера компонента React проверит, есть ли какая-либо высокоприоритетная задача в пуле задач. Как следствие, следует избегать задач, интенсивно использующих ЦП, которые выполняются в одном компоненте, а не распределены по нескольким компонентам.

https://blog.codeminer42.com/everything-you-need-to-know-about-concurrent-react-with-a-little-bit-of-suspense/
👍5🔥2