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

Вышла новая версия библиотеки React Query. Точнее, теперь она называется TanStack Query. Разработчик провел ребрендинг и теперь библиотека не привязана к какому-то конкретному одному фреймворку. Помимо React планируется поддержка Vue, Svelte и Solid.

Кроме самого ребрендинга в 4ой версии появились новые фичи.

Поддержка офлайна. Query теперь может работать с любыми асинхронными данными и не зависит от того, доступна ли сейчас сеть. Также появился Network mode, который позволяет разрабатывать offline-first приложение. Это особенно удобно, если разрабатываете PWA приложение и кэшируете данные в Service Worker или в localStorage.

Улучшение производительности. С 4ой версии Tracked Queries стало поведением по умолчанию. При использовании данной фичи, компонент использующий Query будет ререндерится только при изменении использованных пропов query. Например, если вы не используете стейт isSuccess, то компонент не будет ререндерится, если он изменился. Более подробно написано здесь.

Персистентность. Есть возможность сохранять Query Cache во внешнее хранилище, например, в localStorage. Для того, чтобы подключить внешнее хранилище для кэша, нужно использовать адаптеры SyncStoragePersister и AsyncStoragePersister.

Поддержка React 18. В адаптере для React теперь используется useSyncExternalStore для поддержки конкурентного режима.

https://tanstack.com/blog/announcing-tanstack-query-v4
👍9🔥4
Изучаем шейдеры и React Three Fiber

Three.js и его адаптер React Three Fiber используют WebGL для отрисовки сцен на экране. В свою очередь, WebGL использует шейдеры. Внутри Three.js уже есть встроенные шейдеры материалов: MeshNormalMaterial, MeshPhysicalMaterial и другие. Стандартные шейдеры ограничивают потенциал использования WebGL, поэтому Three.js позволяет создавать и использовать собственные шейдеры.

Максим Хекель в своем блоге рассказал про шейдеры, их виды и показал примеры их использования с React Three Fiber. Кроме самописных шейдеров существуют библиотеки для декларативного создания материалов – Lamina. С помощью композиции слоев можно создать новый материал, используя встроенные слои.

https://blog.maximeheckel.com/posts/the-study-of-shaders-with-react-three-fiber/
👍3
Гайд по ре-рендерам React

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

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

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

Одним из полезных паттернов предотвращения ре-рендера, особенно для тяжелых компонентов, является композиция и прокидывание компонента как проп. В базовом случае можно прокидывать компонент как children.

const ComponentWithScroll = ({ children }) => {
const [value, setValue] = useState({});

return (
<div onScroll={setValue}>
{children}
</div>
)
}

const App = () => {
return (
<ComponentWithScroll>
<HeavyComponent />
</ComponentWithScroll>
)
}


В компоненте ComponentWithScroll проп children не будет зависеть от изменения стейта и вследствие чего не будет происходить его ре-рендер.

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

https://www.developerway.com/posts/react-re-renders-guide
👍14
Обзор способов локализации React приложений

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

react-i18next
Библиотека для перевода локалей на несколько языков:
- Возможность хранения переводов как локально в json файлах, так и на стороннем сервере, подгружая локали через плагин на бэкенде.
- Поддержка TypeScript: типизация ключей.
- Есть хуки для перевода строк и компонент Trans для перевода JSX дерева.
- Есть поддержка популярных фреймворков: Next.js, Gatsby, Remix.

import React from 'react';
import { useTranslation } from 'react-i18next';

export function MyComponent() {
const { t, i18n } = useTranslation();
// or const [t, i18n] = useTranslation();

return <p>{t('my translated text')}</p>
}


react-intl
Библиотека для интернационализации приложения для разных локаций. Использует браузерное API Intl для интернационализации чисел, дат, относительного времени и плюрализации.
Есть как хуки, так и компоненты. Для каждого типа данных есть свой компонент. Например FormattedDate для дат, FormattedNumber для чисел, FormattedMessage для текстовых строк. Чаще всего пользуются последним – FormattedMessage. Также есть поддержка TypeScript.

import {FormattedRelative, useIntl} from 'react-intl';
const MS_IN_DAY = 1e3 * 3600 * 24

const PostDate = ({date}) => {
const intl = useIntl()
return (
<span noscript={intl.formatDate(date)}>
<FormattedRelativeTime value={(Date.now() - date)/MS_IN_DAY} unit="day"/>
</span>
)
});


LinguiJS
Библиотека использует ICU Message Format – синтаксис для выражения сообщений, как и react-intl. Библиотека предлагает использовать компонент Trans, внутри которого может быть JSX дерево. Используя babel макросы, LinguiJS переводит теги Trans в ICU MessageFormat. После чего вместо текстовых строк вставляет перевод. Например:

<p>
<Trans id="msg.docs">Read the <a href="/docs">documentation</a>.</Trans>
</p>


В файле c переводом, ключом перевода сообщения выше будет строка Read the <0>documentation</0>..

Также в библиотеке есть CLI скрипты для извлечения сообщений из приложения и компиляции JS файла с локалями.
👍4
Docusaurus 2.0

Вышла новая версия генератора статических сайтов Docusaurus. Он позволяет создавать сайты на React с фокусом на контент и поддерживает Markdown разметку из под коробки. По словам разработчиков, Docusaurus как create-react-app, но для создания документации, блогов и лендингов.

В новой версии появились новые фичи:
- MDX. Можно добавлять интерактивные React компоненты в Markdown разметку.
- Плагины. У Docusaurus модульная архитектура с системой плагинов. Основные фичи, такие как блог, документация, страницы и поиск можно улучшать плагинами.
- Темизация. Возможность очень гибкой кастомизации стилей, либо создание и использование своей собственной темы.

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

https://docusaurus.io/blog/2022/08/01/announcing-docusaurus-2.0
👍6
Различие между useEffect и useLayoutEffect

Хуки useEffect и useLayoutEffect предназначены для выполнения сайд-эффектов в компоненте и имеют одинаковые сигнатуру. Но цели их использования разные.

useEffect запускается асинхронно после отрисовки браузером DOM изменений.

useLayoutEffect запускается синхронно после DOM изменений, до отрисовки браузера.

Это значит, что если необходимо делать DOM изменения или какую-либо анимацию, то больше подходит useLayoutEffect. В остальных случаях необходимо использовать useEffect. Если выполнять DOM изменения в useEffect, то изменение отобразится в следующем тике браузерного рендера, что приведет к эффекту “мерцания”.

В React 18 было изменено поведение useEffect. Теперь он запускается синхронно, если это результат дискретного ввода. Дискретный ввод — это тип события, при котором результат одного события может повлиять на поведение следующего, например клик. Есть следующий пример:

const App = () => {
const [showToolTip, setShowTooltip] = useState(false);
const buttonRef = useRef();
const tooltipRef = useRef();

useEffect(() => {
if (buttonRef.current == null || tooltipRef.current == null) return;

const { left, top } = buttonRef.current.getBoundingClientRect();
tooltipRef.current.style.left = ${left + 120}px;
tooltipRef.current.style.top = ${top - 20}px;
}, [showToolTip]);

return (
<div>
<button ref={buttonRef}
onClick={() => setShowTooltip(prevState => !prevState)}>
Toggle tooltip
</button>

{showToolTip &&
(<div ref={tooltipRef}>
This is a Tooltip!
</div>)}
</div>
)
};


Если запустить пример выше в React 17, то при клике на кнопку произойдет эффект “мерцания” – сначала тултип отобразится, потом расположится в нужной позиции. Если использоваться useLayoutEffect, то проблема исчезнет. Если запустить пример в React 18, то эффекта “мерцания” не будет и с useEffect, т.к. эффект произошел из-за дискретного ввода – клика по кнопке.

https://blog.saeloun.com/2022/07/28/difference-between-useeffect-and-useeffectlayout-hooks
👍17
Mantine 5.0 – полнофункциональная библиотека компонентов

Mantine – библиотека компонентов для React 18, написанная на TypeScript и Emotion. Включает более 100 готовых компонентов и 40 хуков.

Библиотека разделена на модули, которые можно устанавливать по необходимости. Например, есть модули для работы с формами (аналог react-hook-form) и для работы с датами (компоненты календаря, выбора даты). Также есть модуль для обеспечения серверного рендера компонентов.

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

import { Slider } from '@mantine/core';
import { useHover } from '@mantine/hooks';

export function SliderHover() {
const { hovered, ref } = useHover();

return (
<Slider
defaultValue={40}
min={10}
max={90}
ref={ref}
label={null}
styles={{
thumb: {
transition: 'opacity 150ms ease',
opacity: hovered ? 1 : 0,
},

dragging: {
opacity: 1,
},
}}
/>
);
}


https://mantine.dev/
👍11
Как избежать useEffect с помощью ref колбеков

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

const ref = React.useRef(null)

return <input ref={ref} defaultValue="Hello world" />


Одна из типичных задач при работе с рефом – сделать фокус у инпута при инициализации компонента. Один из вариантов, как это можно сделать, через useEffect:

const ref = React.useRef(null)

React.useEffect(() => {
ref.current?.focus()
}, [])

return <input ref={ref} defaultValue="Hello world" />


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

Более оптимальный способ обращения к рефу – через колбек реф. Концептуально реф у React элемента – это функция, которая вызывается после того, как компонент был отрендерен. Поэтому можно передать колбек в реф и получить доступ к DOM узлу только после рендера элемента.

const ref = React.useCallback((node) => {
node?.focus()
}, [])

return <input ref={ref} defaultValue="Hello world" />


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

https://tkdodo.eu/blog/avoiding-use-effect-with-callback-refs
👍16
Создаем функцию контекста в JavaScript

React популяризировал идею распространения значений через контекст, с помощью которого можно избавиться от проп-дриллинга и синхронизировать состояние компонента в разных частях приложения.
Хотя вариант использования контекста в UI фреймворках очевиден, потребность подобного API существует и не только в UI фреймворках. Создадим свою версию Context API для фреймворка юнит тестирования:

describe('calculator: Add', () => {
it("Should correctly add two numbers", () => {
expect(add(1, 1)).toBe(2);
});
});


После успешного прохождения теста в консоль должна выводиться запись: “calculator: Add > Should correctly add two numbers”.
Для того, чтобы это сообщение вывелось, нам нужно как-то прокинуть описание describe в функцию it. Для этого нам поможет концепция контекста.
Эвятар Алуш в своей статье на Smashing Magazine поделился своей реализацией контекста, которую он использовал в библиотеке для валидации форм Vest.

function createContext() {
let contextValue = undefined;

function Provider(value, callback) {
contextValue = value;
callback();
contextValue = undefined;
}

function Consumer() {
return contextValue;
}

return {
Provider,
Consumer
}
}


https://www.smashingmagazine.com/2022/08/react-context-propagation-javanoscript/
👍6
Мигрируем с Create React App на Vite

Если вы задумывались о миграции приложения с Create React App на Vite, то Катал Мак Доннача в своем блоге собрал инструкцию как это сделать безболезненно.

Единственный минус Vite при работе с проектом на TypeScript – он не проверяет типы при сборке, а сразу транспилирует в JavaScript с помощью esbuild. Поэтому скорость сборки в 20-30 быстрее чем собирать с проверкой типов через tsc. Если это критично, то процесс сборки можно дополнить командой проверки типов tsc --noEmit. В остальном, Vite умеет все то же самое что и CRA, но гораздо быстрее.

https://cathalmacdonnacha.com/migrating-from-create-react-app-cra-to-vite
👍5
Используем React Query вместе с React Router

В React Router 6.4 добавится концепция получения данных – loader и action, как в фреймворке Remix.
Используя проп loader можно объявить, какие данные нужно запросить для отображения роута и получить их в роут через хук useLoaderData. Для изменения данных и их инвалидации используется проп action, а вызывается он при сабмите формы. Однако, React Router не берет на себя обязанность кэширования данных, поэтому имеет смысл использовать библиотеки запросов с кэшированием, например, React Query.

Доминик Дорфмайстер рассказал, как можно объединить React Router и React Query вместе, чтобы использовать преимущества обеих библиотек. React Router вызывает loader получения данных раньше, чем компонент монтируется, а React Query умеет кэшировать данные и дает возможность использовать API запроса, например, refetchOnWindowFocus.

// src/routes/contacts.jsx
import { useQuery } from '@tanstack/react-query'
import { getContact } from '../contacts'

// ⬇️ define your query
const contactDetailQuery = (id) => ({
queryKey: ['contacts', 'detail', id],
queryFn: async () => getContact(id),
})

// ⬇️ needs access to queryClient
export const loader =
(queryClient) =>
async ({ params }) => {
const query = contactDetailQuery(params.contactId)
// ⬇️ return data or fetch it
return (
queryClient.getQueryData(query.queryKey) ??
(await queryClient.fetchQuery(query))
)
}

export default function Contact() {
const params = useParams()
// ⬇️ useQuery as per usual
const { data: contact } = useQuery(contactDetailQuery(params.contactId))
// render some jsx
}


Компонент, где объявляется роут:

const queryClient = new QueryClient()
export default function Routes() {
return (
<Route
path="contacts/:contactId"
element={<Contact />}
// ⬇️ pass the queryClient to the route
loader={contactLoader(queryClient)}
/>
);
}


Обратите внимание на то, что loader - не хук, поэтому не может использовать хук useQueryClient для получения инстанса клиента, и его нужно прокидывать в loader вручную.
На данный момент React Router 6.4 еще находится в бете, но уже можно посмотреть на сайте документации, как будут работать новые концепции получения данных.

https://tkdodo.eu/blog/react-query-meets-react-router
👍11👎3
Почему React ре-рендерит

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

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

React оптимизирует процесс рендера, поэтому сам по себе ре-рендер не имеет большого значения. Однако в некоторых случаях ре-рендер “тяжелого” компонента может занять много времени и повлиять на производительность приложения. В случаях, когда нужно оптимизировать количество ре-рендеров, используют хуки useMemo и useCallback.

useMemo используется для кэширования вычислений между ре-рендерами. Также useMemo используется для сохранения ссылки на одно и то же значение между ре-рендерами для передачи в пропсы мемоизированного компонента. useCallback делает то же самое, что и useMemo, но только для функций.

https://www.joshwcomeau.com/react/why-react-re-renders/
https://www.joshwcomeau.com/react/usememo-and-usecallback/
👍7
React Awesome Reveal

Библиотека для React, которая добавляет анимацию раскрытия элемента используя Intersection Observer API. Библиотека использует Emotion для объявления стилей анимаций.
Также библиотека поддерживает Tree-shaking и серверный рендер. Поддерживается большинство стандартных анимаций из библиотеки Animate.css. Есть возможность каскадного применения анимации к дочерним элементам.


<Fade cascade>
<p>I enter first...</p>
<p>...then comes my turn...</p>
<p>...and finally you see me!</p>
</Fade>


https://github.com/morellodev/react-awesome-reveal
👍5
Клиентский рендер vs серверный рендер

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

В гайде написано про то, как можно настроить конфиг webpack для оптимальной работы приложения: создание vendor файла и preload чанков приложения. Для поддержки SEO необходима генерация sitemap.xml, которую можно создавать при сборке приложения.

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

https://github.com/theninthsky/client-side-rendering
👍5
Миграция на React Router v6: подводные камни и альтернативы

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

Если приложение большое, то облегчить процесс миграции поможет библиотека react-router-dom-v5-compat. С помощью нее можно поэтапно мигрировать на новую версию, сохраняя работоспособность приложения.

https://habr.com/ru/company/alfa/blog/686954/
🔥4👍1
Использование хука useSyncExternalStore

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

Для примера рассмотрим хук useLocation из библиотеки react-router. Он возвращает объект с несколькими атрибутами.

function CurrentHash() {
const { hash } = useLocation();
return <div>{hash}</div>;
}



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

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

- subscribe: функция, которая вызывает колбек при изменении значений.
- getSnapshot: функция, которая возвращает текущее значение стора.
- getServerSnapshot: функция, которая возвращает значение стора во время серверного рендеринга.

Чтобы реализовать через useSyncExternalStore селектор location, необходимо установить библиотеку history. Перенесем API history на аргументы useSyncExternalStore:

- history.listen: подписки на изменения.
- history: текущее значение.

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

function useHistorySelector(selector) {
return useSyncExternalStore(history.listen, () =>
selector(history)
);
}

function CurrentPathname() {
const pathname = useHistorySelector(
(history) => history.location.pathname
);
return <div>{pathname}</div>;
}

function CurrentHash() {
const hash = useHistorySelector(
(history) => history.location.hash
);
return <div>{hash}</div>;
}
👍13🔥2
React и композиция функций

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

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

Чтобы избавиться от дублирования кода, можно реализовать проверки и рендер в отдельных компонентах и вложить их в друг друга:

const MyPage = ({ user = {}, signIn, features = [], log }) => {
return (
<>
<AuthStatusProvider>
<FeatureProvider>
<LogProvider>
<StandardLayout>
<div className="content">{/* our actual page content... */}</div>
</StandardLayout>
</LogProvider>
</FeatureProvider>
</AuthStatusProvider>
</>
);
};


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

const compose = (...fns) => (x) => fns.reduceRight((y, f) => f(y), x);
const withProviders = compose(
withUser,
withFeatures,
withLogger,
withLayout
);
export default withProviders;


Теперь решения сквозных проблем собраны и изменяются в одном месте. Для использования в компоненте нужно импортировать HOC withProviders:

const MyPage = ({ user = {}, signIn, features = [], log }) => {
return <>{/* our actual page content... */}</>;
};
const MyPageWithProviders = withProviders(MyPage);


https://medium.com/javanoscript-scene/why-every-react-developer-should-learn-function-composition-23f41d4db3b1
👍9
Обработка ошибок в React

В приложении могут возникать самые разные ошибки: от ошибки сети до неправильной работы хука в сторонней библиотеке. Если ваше приложение не будет обрабатывать такие ошибки, то оно может сломаться, отображая пользователю белый экран. В React для обработки ошибок используется Error Boundaries – механизм, когда ошибка в дереве компонентов всплывает до компонента обработчика ошибки и как-то обрабатывает его, например, отображая компонент-заглушку. Компонент обработки ошибок становится Error Boundaries, если он классовый и реализованы методы static getDerivedStateFromError или componentDidCatch.

У Error Boundaries есть недостаток, он не обрабатывает ошибки, которые возникли в следующих случаях:
- обработка событий;
- асинхронный код (setTimeout или requestAnimationFrame);
- во время SSR;
- возникли в Error Boundaries;

Также нет механизма повторного рендера дочернего компонента у Error Boundaries для восстановления приложения.

Чтобы обойти эти ограничения, можно использовать библиотеку react-error-boundary. Ее преимущество в том, что она позволяет восстановить работу приложения после ошибки. Также есть хук для обработки ошибок в асинхронном коде. Пример работы библиотеки:

import {ErrorBoundary} from 'react-error-boundary'

function ErrorFallback({error, resetErrorBoundary}) {
return (
<div role="alert">
<pre>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
)
}

const ui = (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={() => {
// reset the state of your app so the error doesn't happen again
}}
>
<ComponentThatMayError />
</ErrorBoundary>
)


https://github.com/bvaughn/react-error-boundary
👍15🔥2
Под капотом у Mobx. Пишем свою реактивную библиотеку с нуля

Когда начинаете использовать Mobx, то кажется, что внутри него используется какая-то магия. Но если посмотреть исходники, то окажется, что все написано на JS и используются стандартные объекты.

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

Григорий Гаврилов в статье на Хабре объяснил, как работает Mobx под капотом, реализовав основное API библиотеки.

https://habr.com/ru/post/689374/
👍10
Будущее рендеринга в React

В текущий момент есть два подхода для рендеринга приложений на React:

- Client-Side Rendering. Сервер отдает базовый HTML и JS бандл и уже в браузере происходит рендеринг и получение данных по API.

- Server-side rendering. Получение данных и рендеринг приложения происходит на стороне сервера с помощью renderToString, который возвращает HTML для передачи клиенту. После получения HTML и JS на клиенте происходит гидратация.

У обоих из этих подходов есть свои плюсы и минусы в терминах Web Vitals, о которых пишет автор статьи. Новые подходы к рендеру приложения на React предназначены для решения основных минусов текущих подходов.

Streaming SSR. Новое API renderToPipeableStream позволяет в связке с Suspense разделить приложение на сегменты, каждый из которых будет рендериться независимо от остальных. При успешном рендере сегмента, HTML будет передаваться на клиент и вставляться в свое место в DOM.

Server components. Позволяет полностью рендерить компоненты приложения на сервере и не требует гидратации на клиенте. Так как компоненты рендерятся только на сервере, то имеют полный доступ к бэкенду и могут обращаться к БД. Один из вариантов использования такого подхода – тяжелые для рендера компоненты, которые будут быстрее рендериться на сервере, чем в браузере пользователя.

Server components еще находятся в альфа версии и недоступны для использования. Streaming SSR также еще официально не зарелизина. Команда React планирует, что разработчики не будут напрямую использовать новые подходы в своих проектах, т.к. они будут сложными в интеграции. Вместо этого, новые подходы рендера должны появиться в фреймворках, которые предоставят более простой интерфейс для работы. Например, новая версия Next.js Layouts RFC должна будет поддержать новые подходы рендера React.

https://prateeksurana.me/blog/future-of-rendering-in-react/
👍8
Как получать данные в React

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

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

const commentsPromise = fetch('/get-comments');

const Comments = () => {
useEffect(() => {
const dataFetch = async () => {
// just await the variable here
const data = await (await commentsPromise).json();

setState(data);
};

dataFetch();
}, [url]);
}


https://www.developerway.com/posts/how-to-fetch-data-in-react
👍6👎1