Заметки про React – Telegram
Заметки про React
3.78K subscribers
34 photos
8 videos
485 links
Короткие заметки про React.js, TypeScript и все что с ним связано
Download Telegram
useSignal() — это будущее веб-фреймворков

Signal — это способ хранения состояния приложения, аналогичный useState() в React.

Ключевое различие между Signal и React стейтом в том, что Signal возвращает геттер и сеттер, а React стейт возвращает значение и сеттер.

Miško Hevery сделал сравнение Signal и хуков в React. Signal является реактивным, т.е. он должен отслеживать, кто заинтересован в состоянии, и уведомлять подписчиков об изменении состояния. Это достигается с помощью наблюдения за контекстом, в котором вызывается геттер, создающий подписку.

useState() возвращает значение состояния, а не геттер. React не важно как используется стейт, он будет ре-рендерить сразу все при изменении состояния.

https://www.builder.io/blog/usesignal-is-the-future-of-web-frameworks
👍14👎1
Как избежать хитрых ловушек в асинхронных стейт менеджерах

Иван Буряк и Трэвис Тернер из Злых Марсиан поделились опытом, как избежать хитрых ловушек при работе асинхронными стейт менеджерами в React. Примеры таких стейт менеджеров: Logux, Replicache, RxDB и WatermelonDB. Они позволяют создавать Offline-first сайты, сохраняя данные стейта в локальное хранилище браузера, например, в IndexedDB.

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

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

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

https://evilmartians.com/chronicles/how-to-avoid-tricky-async-state-manager-pitfalls-react
👍8
Релиз Next.js 13.2

Состоялся релиз минорной версии Next.js 13.2. В новой версии основные изменения касаются работы приложения внутри папки app. Часть изменений:

- Встроенная поддержка SEO через Мета-теги

Экспорт переменной metadata или функции generateMetadata() позволяет установить Мета-теги для страницы. Можно использовать как в компонентах страниц, так и в layout:

// app/layout.tsx

import type { Metadata } from 'next';

export const metadata: Metadata = {
noscript: 'Home',
denoscription: 'Welcome to Next.js',
};


- Кастомный обработчик API роутов

Одними из недостающих фич папки app были API роуты из папки pages/api. В версии 13.2 добавлена фича API роутов в папку app, которая позволяет принимать и обрабатывать запросы, используя fetch Request и Response. Обработчики объявляются в файле route.ts и экспортируются под именем HTTP метода.

// app/items/route.ts

export async function GET() {
const cookieStore = cookies();
const token = cookieStore.get('token');

return new Response('Hello, Next.js!', {
status: 200,
headers: { 'Set-Cookie': token=${token} },
});
}


- Поддержка MDX в серверных компонентах

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

- Статическая типизация ссылок

Адрес href у ссылок Link будет проверяться TypeScript на правильность ввода. Эта фича включается в конфиге и будет работать только в папке app.

https://nextjs.org/blog/next-13-2
👍12👎2
Понимание серверных компонентов в React 18 и Next.js 13

Серверные компоненты – это новая концепция, представленная в React 18 и была реализована в Next.js 13 в папке /app. Серверные компоненты позволяют рендерить компоненты на сервере и уменьшить объем JS отправляемого клиенту.

Все компоненты Next.js в папке /app по умолчанию являются серверными компонентами. Чтобы сделать компонент клиентским, нужно добавить директиву ’use client’; в начало файла.

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

https://programmingwithmosh.com/react/understanding-server-components-in-react-18-and-next-js-13/
👍10
Evolu – хуки для local-first разработки

Библиотека для создания local-first приложений. Поддерживает синхронизацию со сквозным шифрованием с использованием CRDT. Для локального хранения данных использует SQLite WASM. Особенности:

- Типизированная схема данных.
- Реактивные запросы.
- Работа в режиме реального времени: синхронизация при восстановление сети.
- Вместо SQL запросов используется типобезопасный query builder.

Описание схемы и создание хуков:

import * as S from "@effect/schema";
import * as E from "evolu";

const TodoId = E.id("Todo");
type TodoId = S.Infer<typeof TodoId>;

const TodoTable = S.struct({
id: TodoId,
noscript: E.NonEmptyString1000,
isCompleted: E.SqliteBoolean,
});
type TodoTable = S.Infer<typeof TodoTable>;

const Database = S.struct({
todo: TodoTable,
});

const { useQuery, useMutation, useOwner, useOwnerActions, useEvoluError } =
E.createHooks(Database);


Выполнение запросов:

const { rows } = useQuery((db) =>
db
.selectFrom("todo")
.select(["id", "noscript"])
.orderBy("updatedAt"),
// (row) => row
({ noscript, ...rest }) => noscript && { noscript, ...rest }
);


https://github.com/evoluhq/evolu
👍3
Читаем исходный код – Chakra UI

Chakra UI – популярная UI библиотека для React. Она модульная и поддерживает кастомизацию компонентов.

Алекс Кондов изучил исходный код библиотеки и поделился интересными абстракциями, которые он нашел. Будет полезно изучить код тем, кто занимается разработкой UI библиотеки.

Пример создания контекста:

export const [ButtonGroupProvider, useButtonGroup] =
createContext<ButtonGroupContext>({
strict: false,
name: 'ButtonGroupContext',
})

export function createContext<T>(options: CreateContextOptions<T> = {}) {
// ...
const Context = createReactContext<T | undefined>(undefined)
// ...

function useContext() {
const context = useReactContext(Context)

if (!context && strict) {
const error = new Error(
errorMessage ?? getErrorMessage(hookName, providerName),
)
// ...
throw error
}

return context
}

return [Context.Provider, useContext, Context] as CreateContextReturn<T>
}


https://alexkondov.com/reading-code-chakra-ui/
👍9🔥2👎1
Почему вы должны использовать React фреймворк

При создании проекта на React, используйте фреймворк, например, Next.js, Gatsby или Remix. Ли Робинсон объяснил, почему это нужно делать:
- Меньше времени на подключение инструментов, больше времени на создание продукта.
- Более легкая адаптация и обучение новых разработчиков.
- Гибкость для различных стратегий рендеринга (браузерная или серверная).
- Меньше “велосипедов” в проекте.
- Есть готовые инструменты для деплоя проекта.

https://leerob.io/blog/react-frameworks
👎9👍5
Эффективный HOC

HOC – концепция пришедшая из функционального программирования. Это функция, которая принимает компонент и возвращает его с дополнительной логикой.

Хотя эта концепция предоставляет безграничное множество вариантов использования, для практичности нужно ограничиться только добавлением дополнительной логики или компонента обертки. В HOC нужно избегать неожиданного поведения: никаких изменений компонента и его пропсов.

Слава Князев в своем блоге написал туториал по HOC. В нем он описал, что можно и нельзя делать с помощью HOC.

Пример HOC логирования:

const withPropsLogger = (Component) => (
(props) => {
console.log(props);
return <Component {...props}/>
};
);


https://www.bbss.dev/posts/effective-hocs/
👍3🔥1
dnd-kit – drag&drop библиотека для React

Легковесная, модульная и расширяемая библиотека для перетаскиваний в React. Основные фичи:

- Возможность кастомизации алгоритма обнаружения коллизий, рендер оверлея во время переноса и многое другое.
- Поддержка нескольких методов ввода: клавиатура, мышь, touch, pointer.
- Для работы с React предоставляет два хука: useDraggable и useDroppable.
- 0 внешних зависимостей и модульная: ядро библиотеки весит 10Кб.
- Возможность кастомизации анимаций, переходов, стилей и т.д.
- Пресеты: есть готовый пресет @dnd-kit/sortable для создания сортируемых блоков.

Библиотека не использует HTML5 Drag and drop API из-за ограничений в API. В этом API не поддерживаются сенсорные устройства и нет возможности детальной кастомизации поведения. Главный недостаток отказа от HTML5 Drag and drop API в том, что вы не сможете перетаскивать файлы с рабочего стола компьютера или между окнами.

https://docs.dndkit.com/
👍7🔥6
Forwarded from Сова пишет…
Там новая документация реакта наконец-то релизнулась.
Вместе с новым адресом. Старый теперь тоже перенаправляет сюда

https://react.dev/
🔥202
Релиз TypeScript 5.0

Вышла стабильная версия TypeScript 5.0. Авторы обещают, что у большинства разработчиков обновление пройдет гладко.

После RC есть небольшие изменения, основное из них – минимальная поддерживаемая версия Node.js 12.20.

Кроме изменений, описанных в RC, есть другие изменения:

Улучшение enum

Теперь все enum будут enum перечислениями: каждый элемент enum будет иметь уникальный тип. Если в TypeScript 4.9.5 такой код работает:

enum E {
Foo = 10,
Bar = 20,
}

function takeValue(e: E) {}

takeValue(E.Foo);
takeValue(123);


То в TypeScript 5.0 вызов функции takeValue(123) будет выбрасывать ошибку, т.к. 123 не равен ни одному типу E.

Поддержка export type *

// models/vehicles.ts
export class Spaceship {
// ...
}

// models/index.ts
export type * as vehicles from "./vehicles";

// main.ts
import { vehicles } from "./models";


Улучшение поддержки JSDoc

Добавлена поддержка @satisfies и @overload в документации JSDoc.

https://devblogs.microsoft.com/typenoscript/announcing-typenoscript-5-0/
👍4🔥3
Библиотека для анимаций AutoAnimate

AutoAnimate – это одна из наиболее простых библиотек для анимаций, которая запускается одной командой:

import { useAutoAnimate } from '@formkit/auto-animate/react'

function MyList () {
const [animationParent] = useAutoAnimate()
return (
<ul ref={animationParent}>
{/* 🪄 Magic animations for your list */}
</ul>
)
}


Библиотека подходит для простых анимаций и анимирует как сам элемент, на который навешен реф, так и прямые дочерние элементы. Анимация запускается, когда происходит одно из событий:
- Дочерний элемент добавлен в DOM.
- Дочерний элемент удален из DOM.
- Дочерний элемент перемещен в DOM.

AutoAnimate поддерживает кастомизацию анимации: можно самому определить функцию, которая будет возвращать KeyframeEffect.

https://auto-animate.formkit.com/
👍7
This media is not supported in your browser
VIEW IN TELEGRAM
Красивые эффекты с WebGL Render Targets

Максим Хекель сделал руководство по созданию оптических иллюзий и эффектов переходов с помощью WebGL Render Targets.

https://blog.maximeheckel.com/posts/beautiful-and-mind-bending-effects-with-webgl-render-targets/
7👍1
Что такое Vite и почему вы должны использовать его вместо CRA

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

Vite работает гораздо быстрее. Вместо пересборки всего билда, Vite работает по другому. Зависимости приложения, которые редко меняются, упаковываются в один бандл. А исходный код приложения не упаковывается в бандл, а распространяется через нативный ESM. Для production сборки используется бандлинг через Rollup.

https://luketheweb.dev/blog/what-is-vite-and-why-should-you-use-it-instead-of-create-react-app
👍12👎1
Ленивая загрузка роутов в React Routes

В React Router 6.4 была представлена концепция “Data Router”, основное внимание которого уделяется разделению получения данных и рендеринга для исключения “водопадов” загрузки данных.

В React Router 6.9 появилась возможность ленивой загрузки роутов с компонентом и функцией получения данных. Пример:

// app.jsx
import Layout, { getUser } from `./layout`;
import Home from `./home`;

const routes = [{
path: '/',
loader: () => getUser(),
element: <Layout />,
children: [{
index: true,
element: <Home />,
}, {
path: 'projects',
lazy: () => import("./projects"), // 💤 Lazy load!
children: [{
path: ':projectId',
lazy: () => import("./project"), // 💤 Lazy load!
}],
}],
}]

// projects.jsx
export function loader = () => { ... };
export function Component() { ... }

// project.jsx
export function loader = () => { ... };
export function Component() { ... }


Обратите внимание на наименование экспортируемых переменных: loader и Component.

React Router может загружать lazy роуты параллельно. При переходе по URL /projects/123 будут параллельно загружены роуты и выполнены loader функции, после чего будет отрендерен компонент.

https://remix.run/blog/lazy-loading-routes
👎10👍3
Мультиязык в Next.js с помощью серверных компонентов

Ян Аманн рассказал, как сделать мультиязычный сайт с помощью next-intl и серверных компонентов в Next.js.

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

Стоит учитывать, что в серверных компонентах нельзя использовать хуки, например, useState и useEffect. В этом случае одним из вариантов хранения состояния на странице может стать URL search params.

https://www.smashingmagazine.com/2023/03/internationalization-nextjs-13-react-server-components/
👍41
React Labs: над чем мы работали – март 2023

В постах React Labs команда React пишет об исследовательских проектах и текущих разработках, которые могут попасть в релиз. С момента последнего релиза произошли большие изменения:

- Серверные компоненты. Достигли соглашения по использованию директивы "use client" для обозначения только клиентских компонентов. Сделали async / await как основной способ получения данных в серверных компонентах, и хук use для клиентских компонентов. Сейчас ведется разработка того, как отправлять данные с клиента на сервер – Server Action.

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

- Метаданные документа. Появилась возможность использовать теги <noscript>, <meta> и <link> внутри компонента, и они будут установлены внутри тега <head>. Это решает проблему поточного серверного рендера.

- React Optimizing Compiler. Команда React продолжает делать компилятор React Forget. Основная цель компилятора в том, чтобы компонент ре-рендерился только когда изменится значение пропа. Сейчас React ре-рендерит компонент, когда изменится ссылка на объект. С React Forget компонент будет ре-рендерится при изменении семантического значения.

- Offscreen Rendering. Эта фича позволяет рендерить компоненты в фоновом режиме без дополнительных затрат на производительность. Похожа на CSS свойство content-visiblity. Большинство разработчиков не будет напрямую работать с offscreen API, а будут взаимодействовать через существующие роутеры и UI библиотеки.

Transition Tracing. Это API позволит определять, когда хук useTransition становится медленнее, и выяснить, почему это происходит.

https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023
👍13👎1
Переосмысление лучших практик React

React 18, наряду с React Server Components, сделал значительный шаг в сторону серверного рендера. Особенно это видно в таких фреймворках как Remix и Next, где поток данных распространяется на сервер, и приложение превращается в MPA с интерактивностью SPA.

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

https://frontendmastery.com/posts/rethinking-react-best-practices/
👍12
React Chrono – гибкий компонент таймлайна

Вышел релиз второй версии библиотеки React Chrono. С помощью этой библиотеки можно рендерить кастомизируемые таймлайны в вертикальной и горизонтальной ориентации. В новой версии появилась возможность рендерить вложенные таймлайны.

https://react-chrono.prabhumurthy.com/
👍8
Написание собственной библиотеки Сигнал

Люк Шафер в своем блоге сделал туториал по созданию собственной библиотеки наподобие Сигнал. Получилась упрощенная версия без оптимизаций, но достаточная, чтобы понять саму концепцию.

Сигнал в основном используется в SolidJS и также был добавлен в Angular, Preact и Qwik. Сигнал можно использовать и в React, используя @preact/signals-react.

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

export function Counter() {
const [count, setCount] = createSignal(0);

return <button onClick={() => setCount(count() + 1)}>{count()}</button>
}


https://www.lksh.dev/blog/writing-your-own-reactive-signal-library/
👍7
Увеличиваем скорость работы Tanstack Table быстрее в 1000 раз

В блоге Jp Camara статья с разбором проблемы с производительностью библиотеки ​​Tanstack Table. Проблема была в том, что при использовании таблицы с группировкой столбцов, рендеринг 50к строк занимал 30-40 секунд. Использовать браузерный профайлер было невозможно из-за слишком медленной работы приложения. Поэтому для оценки скорости рендера и поиска проблемных мест использовался console.time.

Проблема была обнаружена внутри функции группировки библиотеки Tanstack Table:

function groupBy(rows, columnId) {
const groupMap = new Map<any, Row<TData>[]>()

return rows.reduce((map, row) => {
const resKey = `${row.getValue(columnId)}`
const previous = map.get(resKey)
if (!previous) {
map.set(resKey, [row])
} else {
map.set(resKey, [...previous, row])
}
return map
}, groupMap)
}


Здесь использовался спред оператор […previous, row] для конкатенации текущей строки в конец массива. Так как он использовался внутри другого цикла reduce, то сложность функции группировки была O(n^2). Поэтому для 50к строк выполнялось 2,5 миллиарда итераций.

https://jpcamara.com/2023/03/07/making-tanstack-table.html
🔥4👍1