Заметки про React – Telegram
Заметки про React
3.78K subscribers
34 photos
8 videos
485 links
Короткие заметки про React.js, TypeScript и все что с ним связано
Download Telegram
Оптимизация веб шрифтов в 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
Почему мои Jest тесты такие медленные?

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

- Загрузка окружения (`jest-environment-jsdom`), построение графа зависимостей между файлами, загрузка плагинов и запуск дополнительных потоков.
- Заполнение кэша. Первый запуск будет длиться чуть дольше, т.к. Jest необходимо заполнить кэш. Процесс будет идти еще дольше, если происходит транспиляция TypeScript.
- Загрузка файла теста. Перед запуском теста необходимо загрузить или замокать все зависимости, указанные в файле теста и в файле setupTests.ts. Этот шаг можно оптимизировать.
- Выполнение теста.

Можно использовать Chrome DevTools, чтобы записать профиль производительности работы Jest и посмотреть, на что уходит больше всего времени. Автор подметил несколько основных кейсов, которые делают тесты медленными:
- Баррель файлы. Если вы импортируете компонент из библиотеки, то пишите полный путь к компоненту, а не используйте баррель файл. Баррель файл – это index.ts, который реэкспортирует все экспорты. Когда Jest встречает на своем пути баррель файл, то он загружает все экспорты, объявленные в нем.
- Проверьте setupTests.ts, он запускается перед каждым тестовым файлом.
- Если используете TypeScript, то уберите проверку типов при запуске тестов.
- Проверьте настройки Jest, возможно включены неэффективные для локальной разработки параметры запуска тестов.

https://blog.bitsrc.io/why-is-my-jest-suite-so-slow-2a4859bb9ac0
👍6
Ключ к хорошему дизайну компонента – эгоизм

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

Даниэль Ющик в статье на Smashing Magazine написал подробный гайд с примерами по созданию компонентов для дизайн системы.

Автор выделил ключевые моменты, которыми нужно придерживаться при разработке компонентов:

- HTML управляет дизайном компонента. При разработке абстрактного компонента, наприме, Button не стоит отклоняться от нативного поведения базового элемента. Если у нативного элемента есть проп children, то и у абстрактного он должен быть. Иначе это делает компонент более жестким к изменениям, и новым разработчикам придется менять ментальную модель для работы с данным компонентом.

- children заботится сам о себе. Чем больше мы будем пытаться стилизовать содержимое компонента, тем сложнее это будет поддерживать и дорабатывать. Компонент должен стилизовать только себя, а не свое содержимое.

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

<Modal>
<Modal.CloseButton />
<Modal.Header> ... </Modal.Header>
<Modal.Main> ... <Modal.Main>
</Modal>


https://www.smashingmagazine.com/2023/01/key-good-component-design-selfishness/
👍9
Tamagui – универсальный UI kit

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

Библиотека tamagui состоит из ядра @tamagui/core и компилятора @tamagui/static. Компилятор предназначен для генерации и оптимизации CSS стилей для веба. Поддерживает кастомизации, можно изменить тему любого компонента.

https://tamagui.dev/
👍5👎1
Разбираемся в TypeScript с помощью теории множеств

Владимир Клепов написал подробный гайд про устройство типов в TypeScript. Для наглядности применяются определения из теории множеств: объединение A ∪ B , пересечение ​​A ∩ B, разность A \ B , подмножество и надмножество. Например:
- A extends B можно выразить как “A является подмножеством B”.
- Тип объединения | и пересечения & является объединением и пересечением двух множеств.
- Exclude<A, B> можно назвать разностью двух множеств, но с условием что A и B являются объединением.
- never – пустое множество. A & never = never и A | never = A.

Одним из интересных примеров можно выделить то, что TypeScript позволяет объявлять такие выражения: const x: {} = 9;. Это происходит из-за того, что тип {} не значит то же самое, что и пустой объект в JS. Это тип, в котором можно получить доступ к свойствам, но не важно к каким. Чтобы было понятнее, еще один похожий пример валидного выражения: const x: { toString(): string } = 9;. Это связано с тем, что TypeScript под капотом видит примитив как объект. Поэтому TypeScript позволяет выполнять такие выражения, т.к. благодаря автобоксингу JS выражение валидно и можно вызвать x.toString().

https://blog.thoughtspile.tech/2023/01/23/typenoscript-sets/
👍12
Astro 2.0

Вышла новая мажорная версия фреймворка Astro 2.0. Основные изменения:

Коллекция контента.
Это подход к организации контента, с помощью которого можно писать типобезопасный код в Markdown/MDX разметке. Коллекция контента – это любая папка внутри папки src/content, например “blog”, “newsletter”, "products". Внутри нее размещаются Markdown/MDX файлы с разметкой и полями. В корне src/content создается config файл, из которого экспортируется объект, где ключ - это название папки-коллекции, а значение - описание. В описании коллекции указывается Zod схема полей в разметке. После чего Astro проверяет поля в файлах разметки на правильность написания, а также предоставляет типобезопасное API запросов получения контента.

// src/content/config.ts
// –snip–
const blogCollection = defineCollection({ schema: blogSchema });
export const collections = {
'blog': blogCollection
};

// src/pages/work.astro
import { getCollection } from 'astro:content';
const allBlogPosts = await getCollection('blog');
// –snip–


Гибридный рендеринг
В Astro появилась возможность пререндера конкретной страницы. Эти страницы рендерятся во время сборки приложения, что приводит к экономии времени при загрузке страницы. Чтобы страница рендерилась во время сборки, нужно добавить запись:

export const prerender = true;


Другие изменения:
- Редизайн страницы ошибок
- Оптимизация Hot Module Reloading (HMR)
- Используется Vite 4.0

https://astro.build/blog/astro-2/
👍4
Новая документация React готова на 99%

По сообщению Дэна Абрамова для того, чтобы вывести новую документацию из беты, осталось сделать сайт лендинга.

Новая документация по React уже готова и она отличается от текущей:
- Все примеры приведены с использованием хуков, а не классовых компонентов.
- Гораздо больше интерактивных примеров и визуальных диаграмм.
- В гайдах есть задачи для проверки понимания.

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

https://beta.reactjs.org/
🔥33👍91👎1