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

Джуд Хантер в своем блоге рассказал, как самостоятельно реализовать библиотеку для управления состоянием наподобие Zustand.

Одним из преимуществ библиотек для управления состоянием, в отличие от контекста, является то, что изменение стора не вызывает ререндера всего дерева компонентов. Реализовано это за счет использования селекторов в компоненте.

Чтобы показать свою работу, Джуд Хантер создал функцию создания стора и хук для подписки за изменениями. По аналогии с Zustand при создании стора передаются экшены для изменения стора. Код реализации хука селектора:


const useSelector = <STATE,>(
store: {state: STATE; subscribe: any},
selector: (state: STATE) => any,
) => {
const [selectedValue, setSelectedValue]
= useState(selector(store.state))

useEffect(() => {
return store.subscribe(newState => {
setSelectedValue(
selector(newState);
);
});
}, []);

return selectedValue;
}


https://judehunter.dev/blog/how-to-write-your-own-state-management-library
👍4🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Интерактивный WebGL в Next.js

Для лендинга конференции Next.js Conf разработчики из Next.js сделали интерактивную фигуру на WebGL и рассказали в своем блоге о процессе создания.

Для реализации WebGL использовали библиотеки react-three-fiber и drei – утилитарная библиотека для react-three-fiber, в которой собраны основные паттерны. Для постпроцессинга используется библиотека @react-three/postprocessing.

https://vercel.com/blog/building-an-interactive-webgl-experience-in-next-js
👍2
Конференция для JavaScript-разработчиков HolyJS 2022 Autumn

🌐 10–11 ноября — онлайн
👥 20 ноября — офлайн в Москве
(с возможностью удаленного участия для тех, кто не готов добраться)

Программа конференции полностью готова

Из интересного про React:
Сергей Константинов, воркшоп «Пишем игру на React и разбираемся с react-reconciler»
Дмитрий Грош, доклад «Батчинг в React»
Константин Астапов, доклад «How to build large react-redux application without code mess»
Сэм Булатов, доклад «Введение в реактивное программирование»

Если вам хочется на несколько часов отвлечься и побыть среди единомышленников, то приходите на HolyJS. А промокод reactnotes2022JRGpc даст скидку 20% на билеты из категории «Для частных лиц».

Подробности и билеты — holyjs.ru
👍3🔥1
React Query: заполняем кэш запросов

В React Query есть поддержка загрузки данных в Suspense, для этого нужно передать параметр suspense: true в настройки запроса. При использовании данного механизма нужно быть осторожным. Если у вас несколько запросов в одном компоненте, то возникает проблема “водопада” запросов. При рендере компонента React Query сообщает, что необходимо выполнить первый запрос, React ставит компонент на паузу и ждет выполнения. После успешного выполнения запроса, компонент перемонтируется заново и React Query сообщает, что необходимо выполнить второй запрос, и сценарий повторяется. Так возникает “водопад” запросов.

Чтобы избежать подобных проблем, Доминик Дорфмайстер в своем блоге поделился способами предварительного заполнения кэша для запросов.

Во-первых, предварительно загружайте данные до рендера компонента. Если проект поддерживает SSR, то загружайте данные на сервере. Если роутер поддерживает лоадеры, то загружайте в лоадерах.

const issuesQuery = { queryKey: ['issues'], queryFn: fetchIssues }

queryClient.prefetchQuery(issuesQuery)

function Issues() {
const issues = useQuery(issuesQuery)
}


Во-вторых, если у вас данные в списке и нужен отдельный элемент из списка, то его можно получить из кэша:

const data = useQuery({
queryKey: ['todos', 'detail', id],
queryFn: () => fetchTodo(id),
initialData: () => {
return queryClient
.getQueryData(['todos', 'list'])
?.find((todo) => todo.id === id)
},
})


Другой подход – создавать кэш для отдельного элемента после получения данных для списка:

const data = useQuery({
queryKey: ['todos', 'list'],
queryFn: async () => {
const todos = await fetchTodos()
todos.forEach((todo) => {
queryClient.setQueryData(['todos', 'detail', todo.id], todo)
})
return todos
},
})


Минус такого подхода в том, что данные могут устареть до момента, когда они понадобятся, либо эти данные могут вообще не понадобиться.

https://tkdodo.eu/blog/seeding-the-query-cache
👍5👎1
Feature-Sliced Design: эволюция фронтенда для быстрых экспериментов

Небольшой обзор от Евгения Валяева, в котором описывается подход к разработке проекта с использованием FSD.

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

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

https://habr.com/ru/company/inDrive/blog/693768/
👍20🔥7👎3
Бесплатный Community Day HolyJS 2022 Autumn — 11 ноября, онлайн

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

На Community Day такая же насыщенная программа, как и в другие дни конференции. Там будут:
7️⃣ докладов с дискуссиями
2️⃣ воркшопа: улучшаем доступность маркетплейса для незрячих и пишем игру на React
BoF-сессия про микрофронтенды

Бесплатная регистрация на holyjs.ru
👍2🔥2
TanStack Router

Таннер Линсли представил новый проект – TanStack Router. Это масштабируемый роутер для приложений, написанный на TypeScript и не привязанный к конкретному фреймворку.

Автор предлагает сразу много фич из коробки:
- Управление стейтом из URL
- Встроенное кэширование
- Валидация схемы search params
- Автоматический prefetch запросов
- Лоадеры данных на уровне роута
- Code-Splitting

Для создания роутера приложения не требуется JSX, все роуты объявляются через функции. Библиотека находится в статусе беты и пока что есть адаптер только для React.

https://tanstack.com/router/v1
👍12
Forwarded from Сова пишет…
На волне очень приятных эмоций от общения на дискусии, я закончил оформлять подборку статей!

Как проектировать API, что особенного в подборе цветов для веб-сайта, как работает движок V8?

https://news.sova.dev/issues/19-1263486
👍4
Монорепозиторий c Turborepo

Гайд по созданию и настройке для проекта монорепозитория со следующим стеком:
- npm для установки зависимостей и линковки пакетов;
- turborepo для оркестрации задач;
- tsc, postcss-cli и vite для сборки пакетов;
- ladle для демо-стенда;

Такой стек удобен тем, что в нем можно поменять инструмент на любой другой.

Одно из преимуществ Turborepo – кэширование результатов сборки. При автоматизированной сборке на CI кэширование может значительно увеличить скорость работы пайплайнов.

https://habr.com/ru/post/694808/
👍4
Создание форм из JSON схемы

uniforms – библиотека для генерации форм на основе JSON схемы. Структура схемы и валидация может быть любой. Подключение схемы к форме происходит через адаптер. В документации uniforms рекомендуют работать с ajv, наиболее популярной библиотекой для валидации JSON схемы.

Преимущества uniforms:
- автоматическая генерация формы;
- встроенный набор компонентов для отображения любых типов полей;
- создание кастомных полей;
- асинхронная валидация формы;
- поддержка кастомных тем для стилизации;

Пример кода для генерации формы:

import { AutoForm } from "uniforms"
import { createBridge } from "./createBridge" // explained later

function AutomaticForm() {
return <AutoForm schema={createBridge(loginSchema)} />;
}


https://uniforms.tools/
Гайд https://www.vazco.eu/blog/a-novel-schema-first-approach-to-building-forms
👍5👎1
Как работает Framer Motion

Нанда Шахрасяд рассказал, как работает анимация в Framer Motion.

Чтобы сделать плавное изменение CSS свойств между двумя состояниями, используется свойство transition. С его помощью плавно изменяется width, height, transform и другие свойства, но не все. У этого способа есть недостатки:
- Изменение размеров макета у элемента считается менее производительным, чем использование transform.
- Нельзя сделать плавное изменение таких свойств как justify-content, потому что justify-content не анимированное свойство.

Для анимации изменения размеров макета и перемещения, в Framer Motion используется техника FLIP (First, Last, Inverse, Play). При рендере элемента в реф сохраняется его текущее расположение. Если текущее расположение отличается от предыдущего, то вычисляется дельта. Элементу устанавливается стиль transform с полученной дельтой (происходит инверсия) и запускается анимация transform к текущему расположению. Пример анимации изменения позиции:

export default function Motion() {
const squareRef = React.useRef();
const initialPositionRef = React.useRef();

React.useLayoutEffect(() => {
const box = squareRef.current?.getBoundingClientRect();
if (moved(initialPositionRef.current, box)) {
const deltaX = initialPositionRef.current.x - box.x;
const deltaY = initialPositionRef.current.y - box.y;

squareRef.current.style.transform = `translate(${deltaX}px, ${deltaY}px)`;

// animate back to the final position
animate({
…params,
onUpdate: progress => {
squareRef.current.style.transform =
translate(${deltaX * progress}px, ${deltaY * progress}px);
}
})
}
initialPositionRef.current = box;
});

return <div id="motion" ref={squareRef} />;
}


https://www.nan.fyi/magic-motion
👍8
Таймлайн компонента в React

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

Знание порядка вызова хуков может помочь писать компоненты в React правильно и эффективно. Компонент в React - это всего лишь функция, которая возвращает разметку. Хуки дополняют компонент и вызываются в определенном порядке, в соответствии с жизненным циклом компонента.

https://julesblom.com/writing/react-hook-component-timeline
👍12
Доступный drag and drop

React Spectrum зарелизили поддержку drag and drop в React Aria and React Spectrum. Релиз содержит набор хуков для реализации drag and drop с поддержкой мобильных устройств, клавиатуры и screen reader. Особенности:

- Гибкость – хуки включают в себя верхнеуровневое API для основных манипуляцих с элементами: перемещение, изменение порядка, копирование.
- Доступность – поддержка клавиатуры, screen reader, мобильных устройств.
- Совместимость – поддерживает разные форматы данных, используя нативный HTML drag and drop.
- Кастомизация – возможность изменения UI и поведения хуков.


function Draggable() {
let { dragProps, isDragging } = useDrag({
getItems() {
return [{
'text/plain': 'hello world'
}];
}
});

return (
<div
{...dragProps}
role="button"
tabIndex={0}
className={`draggable ${isDragging ? 'dragging' : ''}`}
>
Drag me
</div>
);
}


https://react-spectrum.adobe.com/blog/drag-and-drop.html
👍7👎1
Релиз tRPC v10

После нескольких релиз-кандидатов появилась стабильная мажорная версия tRPC v10.

Основные изменения:
- Улучшенная поддержка TypeScript. Упрощен вывод типов, больше поддержки для IDE. Улучшена производительность для TypeScript.
- Изменена конструкция создания роутера и вызова процедур.
- Мидлвары стали переиспользуемыми.
- Функции процедуры стали переиспользуемыми, и их можно выстраивать в цепочку. Можно сделать публичные и приватные процедуры, добавив мидлвар проверки авторизации.
- Гибкая обработка ошибок: перед отправкой ошибки клиенту есть возможность ее видоизменить.

Если в проекте уже используется tRPC v9, то можно обновиться на v10 поэтапно. После обновления tRPC для роутеров нужно добавить метод interop() и серверный код продолжит работать как раньше.

Пример переиспользуемых процедур:

export const protectedProcedure = t.procedure.use(isAuthed);

export const appRouter = router({
createPost: protectedProcedure.mutation(({ctx}) => {
const session = ctx.session;

// [...]
}),
});


https://trpc.io/blog/announcing-trpc-10
👍5
Использование структур данных в приложениях React

Пример использования основных структур данных в приложениях React от Йоханнес Кеттманн. Большинство разработчиков не используют структуры данных явно и не видят причин их использовать в JavaScript фреймворках. Для этого есть свои причины: в JavaScript не реализовано большинство структур данных, и React плохо работает с кастомными структурами данных.

Знать структуры данных полезно. Неправильный выбор структуры данных может привести к беспорядочному коду. В статье автор собрал примеры использования в приложениях на React таких структур данных, как Map, Set, Stack, Queue и Tree.

https://profy.dev/article/javanoscript-data-structures
👍8
Улучшаем время взаимодействия в React в 4 раза

Практический гайд от инженеров Causal и Ивана Акулова по улучшению производительности React приложения. Уменьшив количество ре-рендеров компонентов, инженеры смогли добиться увеличения скорости работы компонентов в 4 раза. Для определения проблемных мест приложения использовалось профилирование во вкладке Performance и React Profiler. В гайде много скриншотов и видео, а также примеров кода.

https://www.causal.app/blog/react-perf
👍13
Оценка покрытия кода со Storybook test runner

Инструменты оценки покрытия кода тестами позволяют выявить непроверенные пограничные случаи. Это помогает писать более полные тесты и быть уверенным в надежности компонентов. В Storybook для запуска тестов используется Jest, а для описания кейсов Playwright.

С помощью Storybook test runner можно генерировать отчеты покрытия кода. Для генерации отчетов используется библиотека Istanbul. Чтобы использовать Istanbul необходимо установить аддон @storybook/addon-coverage. В гайде описаны шаги установки, а также варианты оформления отчетов.

https://storybook.js.org/blog/code-coverage-with-the-storybook-test-runner/
👍5
Архитектура 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