React Junior
208 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
React Router

Так как в SPA переключение между страницами осуществляется без перезагрузки, необходимо какое-то решение для маршрутизации. Для этого в основном используется React Router.

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

Мы начнем знакомство с роутером с гайда Robin Wieruch (англ.): https://www.robinwieruch.de/react-router/

NPM-пакет, который нам нужен, называется react-router-dom, очевидно, эта реализация предназначена именно для работы в браузере. Разумеется, вся функциональность оформлена в виде React-компонентов и хуков.

🔷 Важные компоненты

🔸 BrowserRouter

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

🔸 Link

Компонент-ссылка, используется вместо обычных a. Вместо атрибута href есть проп to.
При нажатии на Link текущий урл изменяется, но перезагрузки не происходит.

🔸 NavLink

Аналог Link, который знает о текущем активном роуте и может иметь "активное" состояние (класс .active, а также проп `isActive`). Удобно использовать для главного меню сайта, чтобы выделять раздел, который пользователь просматривает в данный момент.

🔸 Route

Компонент отдельного роута. Имеет проп path, содержимое которого сопоставляется с текущим урлом, и проп element, в который нужно передать разметку, которая должна быть отрендерена.
Если указанный роут совпадает с текущим, он рендерится.
Таким образом, атрибут to компонента Link соответствует атрибуту path компонента Route.

🔸 Routes

Обязательный контейнер для элементов Route, которых может быть сколько угодно.
Внутри Routes всегда рендерится только один роут, первый подходящий.

🔸 Outlet

Роуты должны быть единственными потомками компонента Routes (еще могут быть React.Fragment), но их можно вкладывать друг в друга. При этом чтобы внутри родительского компонента отображались вложенные роуты (если они активны), используется компонент Outlet (аналог `props.children`).

🔷 Роуты

🔸 Без роута

У элемента Route может не быть пропа path, например, если это компонент-обертка (`Layout`), которые оборачивает все роуты и выводится всегда.

🔸 Index

Для обозначения корневого роута используется проп index. В этом случае path указывать не нужно.

🔸 Not Found

Если не один роут из списка не подошел, можно вывести запасной вариант - обычно это страница 404. Для этого в пропе path нужно указать *.

🔸 Динамические роуты

Если требуется передать в роуте какой-то динамический параметр, например, id товара на страницу каталога, в компоненте Route его нужно указать с помощью : (`:productId`).

Получить значение параметров можно с помощью хука useParams.

🔸 Вложенные роуты

Если роуты вложены друг в друга, то значения их путей складываются.

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

🔷 Программная навигация

Для программной навигации по роутам используется хук useNavigate, который возвращает функцию navigate. Чтобы перейти на какой-то роут, нужно просто передать его параметром в эту функцию.

🔷 Гет-параметры

В урле кроме основного пути могут быть еще дополнительные параметры запроса (search params). При необходимости их можно получить с помощью хука useSearchParams. Он возвращает стандартный кортеж (массив значений) - первым идет сам объект с параметрами, а вторым - метод для его обновления.

Удобно использовать, например, для сохранения значений различных фильтров.

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

#ссылки #роутинг
👍1👏1
Проект

Небольшой проект для закрепления материала: https://codesandbox.io/s/project-1-react-junior-oso5s?file=/src/App.js

Описание

Это демка интернет-магазина резиновых уточек.

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

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

Кроме того есть отдельная страничка с информацией о магазине.

Данные

Для симуляции получения данных с сервера используются методы getProducts() и getProduct(id). Список продуктов запрашивается в компоненте App (внутри хука useEffect). Состав корзины также хранится здесь.

Стили

Для стилизации используется React JSS.

Приложение обернуто в ThemeProvider, в отдельных компонентах для получения темы используется хук useTheme.

Маршрутизация

Для маршрутизации используется React Router. Все приложение обернуто в компонент BrowserRouter.

Главный компонент приложения - App. Здесь определяются все роуты:

- индексный - компонент Catalog
- роут about - компонент About
- роут cart - компонент Cart
- и вложенный в cart роут с динамическим параметром :productId - компонент ProductView

Также есть дефолтный роут *, связанный с компонентом NotFound.

Все роуты обернуты в роут без пути, связанный с компонентом Layout, который обеспечивает общую разметку.

Чтобы в компоненте Корзины мог отображаться вложенный компонент ProductView, используется компонент Outlet.

В шапке есть маленькое навигационное меню, созданное с помощью компонентов NavLink. Они хранят состояние, активный роут выделяется цветом. Прочие навигационные ссылки сделаны с помощью Link.

Программная навигация

При удалении товара из корзины роут программно изменяется.

Гет-параметры

На странице каталога есть поле поиска по товарам, оно синхронизируется с гет-параметром filter с помощью хука useSearchParams.

Прочее

Для пробы добавлен кастомный хук useFilteredList.

#роутинг #хуки #стили #примерыкода
👏1
Несколько статей

Несколько ссылок, надерганных из предыдущей статьи про роутер (все англ.):

🔸 Структура папок в React проекте за 5 шагов

https://www.robinwieruch.de/react-folder-structure/

Описано 5 способов группировки файлов по папкам в зависимости от размера проекта. От единственного файла, до разделения компонентов по доменам (отдельно компоненты, связанные с юзером, отдельно каталог и т.п.)

В целом ничего нового, но полезно, чтобы составить более оформленное представление.


🔸 CSS в React

https://www.robinwieruch.de/react-css-styling/

Еще один обзор разных способов стилизации приложений, большинство из которых мы уже довольно подробно разобрали. Способы разделены на три стратегии CSS-in-CSS, CSS-in-JS и Utility-First-CSS.

Заинтересовала именно последняя секция, про утилитарный CSS (Tailwind). Там куча разных классов, предполагается, что с их помощью можно настроить все, что нужно, без единой строчки CSS. Например, есть класс py-2, который устанавливает вертикальные паддинги, или border-solid для стиля рамки. Выглядит ужасно, но может быть очень удобно для быстрого наброска/прототипирования/какого-нибудь небольшого демо-проекта.


🔸 Вложенные роуты в React Router 6

https://www.robinwieruch.de/react-router-nested-routes/

Более подробный разбор вложенных роутов. Это когда у вас есть, например, Личный Кабинет пользователя но роуте /user, а в нем две вкладки: Личные данные (`/user/personal`) и История заказов (`/user/orders`). Общая часть страницы отображается всегда, а какая именно вкладка будет видна - зависит от урла и является частью роутинга.

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

Вложенные роуты могут быть динамическими (например, id пользователя). В этом случае мы можем получить конкретное значение с помощью хука useParams.


🔸 Параметры поиска в React Router 6

https://www.robinwieruch.de/react-router-search-params/

Более подробный разбор работы с гет-параметрами. В React Router для этого есть хук useSearchParams, он возвращает актуальный объект URLSearchParams и позволяет изменять его. Чтобы было удобнее, можно написать собственный хук, который превращает URLSearchParams в обычный объект. Или можно воспользоваться уже готовым решением use-query-params.

#проект #роутинг #стили #ссылки
👍2
Документация React Router

Начинаем читать документацию React Router, чтобы узнать его получше.

https://reactrouter.com/docs/en/v6

Сначала общий обзор:

1. React Router DOM

В npm можно найти три пакета: react-router, react-router-dom и react-router-native. В первом находится ядро роутера, а два других - это конкретные реализации для браузера и для нативных приложений. React-router-dom и react-router-native уже импортируют все из react-router, поэтому нам не нужно использовать основной пакет.

2. Роутеры

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

3. Роуты

Есть два способа объявить роуты:
- прямо в JSX-разметке с помощью компонентов Routes и Route
- с помощью хука useRoutes из JS-кода

4. Навигация

Можно управлять роутингом, то есть изменять текущий урл и, соответственно, отображаемые компоненты React. Для этого есть компоненты Link и NavLink (аналоги обычных ссылок), а также компонент Navigate и хук useNavigate для программного управления.

5. Гет-параметры

Для работы с гет-параметрами урла предназначен хук useSearchParams.

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

#документация #роутинг
Роутеры

BrowserRouter

Стандартный роутер для маршрутизации в браузере. Использует History API для управлния урлом и изменения текущего роута. По умолчанию работает с текущим окном, но это можно изменить с помощью пропа window.

Hash Router

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

Memory Router

MemoryRouter хранит всю информацию в обычном массиве и не связан с внешними api. Его удобно использовать для тестирования. У него есть пропсы initialEntries (принимает массив строк) и initialIndex (принимает число), с помощью которых можно установить "исходную" историю маршрутизации.

#документация #роутинг
👍1
Современный технический стек React: самые популярные инструменты

Статья (англ.): https://profy.dev/article/react-tech-stack

Обзор самых популярных инструментов в экосистеме React для решения самых разных задач: от обработки форм до тестирования. Будет полезен начинающим разработчикам, у которых (как у меня) глаза разбегаются, и непонятно, за что хвататься.

Оценка популярности базируется в основном на количестве загрузок в npm, но учитываются и другие источники информации (например, опрос State of JS).

🔶 1. Библиотеки

Next.js - самый популярный React-фреймворк.
Redux - самый популярный стейт-менеджер.
react-query - самая популярная библиотека для запроса данных (или Apollo для проектов, использующих GraphQL).
React Hook Form - самая популярная библиотека для работы с формами.
styled-components и MUI - самые популярные библиотеки для работы со стилями (MUI - библиотека компонентов)

🔶 2. Инструменты разработки

Prettier - для форматирования кода.
ESLint - для статического анализа кода и отлова плохих паттернов.
TypeScript - для проверки типов.

🔶 3. Тестирование

Jest - самый популярный фреймворк для тестирования (в основном юнит-тесты).
React Testing Library - самая популярная библиотека для интеграционного тестирования.
Cypress - самый популярный инструмент для e2e-тестирвания.
Storybook - самый популярный инструмент для тестирования и документации интерфейса.

🔶 4. Workflow

Trunk Based Development - самая распространенная модель разработки, основанная на Git. Для Continuous Integration используются GitHub Actions. Схема довольно простая:

- новая ветка создается от главной
- код пушится в репозиторий
- открывается пулл-реквест
- запускаются все проверки (линтер, проверка типов, тесты)
- проводится код-ревью
- ветка мержится в главную

🟢 Дорожная карта

В заключение автор предлагает "дорожную карту" для погружения в React-экосистему:

1. Разобраться в Trunk Based Development.
2. Начать использовать Next.js.
3. (Опционально) Изучить TypeScript.
4. Использовать ESLint и Prettier.
5. Разобраться в styled-components или MUI для стилизации.
6. Писать тесты с помощью Cypress.
7. (Опционально) Redux.
8. (Опционально) Storybook.

#ссылки #тестирование #стили #инструменты
👍1
React Router. Навигация

Link

Роут указывается в пропе to. Допускаются "относительные" ссылки (у которых в начале нет /), они работают относительно текущего роута (все как у обычных ссылок).

По умолчанию смена роута происходит без перезагрузки страницы, но это поведение можно отменить с помощью пропа reloadDocument (только зачем?).

NavLink

Навигационная ссылка с состоянием "активности". Если роут такой ссылки соответствует текущему роуту приложения, она помечается классом active.

Кроме того, в атрибут style и в атрибут className элемента NavLink можно передать функцию. В качестве параметра она получает объект с полем isActive. Так можно устанавливать динамические стили.

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

Примеры: https://codesandbox.io/s/navlink-react-junior-8g1xen

Кроме того, есть проп end, который убирает активность ссылки, если активен дочерний по отношению к ней роут.
Например, у нас есть ссылка, ведущая на роут /catalog, а текущий активный роут /catalog/pizza. По умолчанию ссылка будет активна, но проп end может это изменить.

Navigate

Это способ управлять роутингом прямо из JSX-разметки, без JS-кода.

Если компонент Navigate рендерится, то происходит изменение роута. То есть он всегда используется с некоторым условием. Под капотом у него используется хук useNavigate, пропсы соответствуют параметрам этого хука (to, replace).

В документации в качестве примера приводится форма авторизации.

Мой вариант: https://codesandbox.io/s/navigate-react-junior-mrp48r?file=/src/pages/Login.js

У нас есть два роута, индексный с формой авторизации и /account. При отправке формы происходит базовая валидация полей, затем данные отправляются на сервер. Если пользователь успешно авторизован, то мы рендерим компонент Navigate с пропом to=/account - происходит переход на страницу Личного кабинета.

#роутинг #примерыкода
React Router. Outlet

Компонент Outlet нужен, усли в приложении есть вложенные роуты. Он используется в родительском роуте в том месте, где нужно вывести контент дочернего роута. Это аналог пропа children для роутов.

https://codesandbox.io/s/outlet-react-junior-d08y8s?file=/src/App.js

Например, есть роут /profile, который представляет личный кабинет пользователя. С ним связан компонент Profile, который рендерит общую информацию о пользователе, а также вкладки Заказы и Баллы лояльности. Каждая вкладка - это отдельный дочерний роут - /profile/orders и profile/loyalty, с каждым из которых связан свой компонент.

Чтобы дочерние роуты выводились, нужно вставить Outlet в нужном месте компонента Profile.

Контекст

Родительский компонент может передавать в дочерние роуты какие-либо данные через проп context элемента Outlet. Таким образом можно поднять состояние из дочерних роутов в родительский. В примере так передается количество баллов лояльности.

Чтобы получить эти данные в дочернем компоненте, нужно использовать хук useOutletContext.

#роутинг #примерыкода
React Router. Вспомогательные функции

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

Их можно найти в документации на страничке с описанием API: https://reactrouter.com/docs/en/v6/api#api-reference

Если при дальнейшем изучении что-то из этого понадобится, то мы сюда вернемся.

#документация #роутинг
React Router. Глубокое погружение

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

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

Прежде всего здесь приведены определения для всех терминов (Location, History Stack, Match и пр.): . Полезно начать именно с них, чтобы правильно воспринимать информацию.

Основные составляющие процесса маршрутизации:

- подписка и манипуляции с History Stack (история навигации пользователя)
- матчинг (сопоставление) урла и роутов
- рендеринг активных роутов

История навигации

В браузере есть объект window.history - история навигации пользователя. Это массив урлов, на которые мы переходим. Благодаря истории можно вернуться на предыдущую просмотренную страницу (кнопка Назад).

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

Для представления текущего урла (window.location) также используется собственная реализация location, более простая и удобная. (Ее можно получить из хука useLocation.)

Для измененения истории навигации предназначены компоненты Link, NavLink, Navigate и хук useNavigate.

Для доступа к текущему урлу и его параметрам - хуки useLocation, useParams, useSearchParams.

Сопоставление роутов

В начале работы React Router составляет конфиг роутинга (route config), который по сути представляет собой просто дерево роутов, созданных с помощью Routes и Route.

Создать такой конфиг можно программно с помощью хука useRoutes (он используется под капотом).

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

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

Роуты без путей

Для некоторых роутов не указывается проп path, и они обрабатываются по особым правилам. Это, например, индексные роуты (рендерятся при точном совпадении родительского роута), а также layout-роуты, которые содержат общую разметку для вложенных роутов, но сами по сути роутами не являются.

Рендеринг

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

Компонент Routes использует Outlet под капотом, чтобы автоматически выводить совпавший роут первого уровня.

Общая схема работы

1. Мы пишем код приложения с компонентами Routes и Route и оборачиваем все в BrowserRouter.
2. BrowserRouter создает объект истории навигации (history), подписывается на его изменения и устанавливает начальный урл (location).
3. Routes рекурсивно обходит своих потомков и создает конфиг роутинга (route config), находит роуты, совпадающие с текущим урлом, собирает все вложенные роуты в массив matches и рендерит первый роут из этого массива.
4. Вы вручную рендерите остальные совпавшие вложенные роуты, используя в нужных местах родительских компонентов Outlet. Каждый Outlet рендерит один следующий роут.
5. Пользователь кликает по компоненту Link.
6. Link вызывает функцию navigate, обращаясь к объекту history.
7. Объект history изменяет урл и оповещает BrowserRouter.
8. BrowserRouter перерендеривается.

#документация #роутинг #подкапотом
React Router. Аутентификация

Пример из документации: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx

Структура приложения

Есть открытая страница PublicPage, доступная по пути /. И есть закрытая страница ProtectedPage, которая должна открываться по пути /protected, но только для авторизованных пользователей. Если пользователь не авторизован, должна открываться форма авторизации.

Создаем три роута (Route): для открытой страницы, для закрытой страницы и для формы авторизации (/login).

Контекст для хранения состояния

Для хранения состояния авторизации используется контекст AuthContext, созданный с помощью метода React.createContext.

Контекст содержит актуальное состояние, а также методы для авторизации и разлогинивания.

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

Компонент-обертка для компонентов с закрытым доступом

Создаем вспомогательный компонент RequireAuth. Он оборачивает контент закрытой страницы (ProtectedPage) и должен рендерить его только в том случае, если юзер авторизован.

Этот компонент получает доступ к контексту (через хук useAuth) и узнает текущий статус авторизации. Если пользователь авторизован, то компонент просто рендерит своих потомков (props.children). В противном случае происходит перенаправление на роут /login с помощью компонента Navigate.

У компонента Navigate указывается проп state. Это дополнительные данные, которые связаны с location, но не отображаются в урле. Их можно будет получить из хука useLocation. Этот прием используется, чтобы сохранить страницу, с которой произошел переход.

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

Форма авторизации

Когда пользователь заполняет и отправляет форму, компонент LoginPage вызывает метод авторизации (из контекста). Если авторизация прошла удачно, происходит переадресация с помощью хука useNavigate - или на страницу, на которую изначально пытались перейти (закрытая страница), если она есть в location.state, или просто на главную страницу приложения.

#документация #роутинг #примерыкода
React Router. Кастомная ссылка

https://stackblitz.com/github/remix-run/react-router/tree/main/examples/custom-link?file=src/App.tsx

Пример создания собственного аналога NavLink - ссылки на роут, которая знает, когда она активна.

Для определения совпадения с текущим роутом используется хук useMatch.

#документация #роутинг #примерыкода
Глубокое погружение в код React. Часть 1. Вводная

Первая часть из серии статей, посвященных разбору кодовой базы React (англ.): https://dev.to/fromaline/deep-dive-into-react-codebase-ep1-prerequisites-33ak

Это вводная часть, которая рассказывает:

- почему React вообще появился (потому что команда разработчиков из Facebook создала сложное приложение с динамическими данными и не смогла справиться с каскадными изменениями интерфейса)
- какова основная идея React (у тебя есть код, который описывает, что должно делать приложение с определенным набором данных. Если данные изменятся, нужно просто перезапустить этот же самый код)
- и как устроен монорепозиторий React (ядро React Core, несколько рендереров для разных сред выполнения и согласователь Fiber Reconciler)

#ссылки #подкапотом
React Router. Lazy loading

https://stackblitz.com/github/remix-run/react-router/tree/main/examples/lazy-loading?file=src/App.tsx

Пример ленивой загрузки компонентов для роутов. Ничего особенного, обычные "ленивые компоненты" с использованием React.lazy для загрузки и React.Suspense для отображения с фоллбэком.

#документация #роутинг #примерыкода #ленивыекомпоненты
Location State

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

У объекта window.history в браузере есть метод pushState(), который мы можем использовать для изменения текущего урла. Казалось бы, при чем тут state, мы же просто добавляем в историю новую запись.

Однако в сигнатуре этого метода три параметра, и урл - последний из них и необязательный. Первым идет state object - объект состояния, в который можно записать все, что угодно. Таким образом, в истории хранится именно состояние, какие-то данные, а урл может и не меняться.

Получить текущее состояние можно из window.history.state.

React Router позволяет удобно пользоваться этой фишкой прямо из объекта location, таким образом состояние привязывается к местоположению, а не к истории.

Чтобы установить state для location, можно использовать проп state компонента Link. В него можно установить любые данные. Также state можно передать в функцию navigate, полученную из хука useNavigate.

Чтобы получить текущий state, нужно использовать хук useLocation. Он возвращает объект location с полем location.state.

Кейсы для использования:

- сохранение предыдущей локации для последующего перенаправления
- отправка данных (обычно урезанных, самых необходимых) для быстрого отображения на новой локации, пока основные данные загружаются

#роутинг #документация #паттерны
React Router. Модальное окно

Пример реализации модального окна с помощью роутера: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src/App.tsx

В приложении есть два контейнера Routes, так что модальное окно может отображаться одновременно с основной страницей. При этом одна ветка роутов использует текущее значение location, а для другой оно задается вручную с помощью пропа location.

Когда модальное окно открывается, текущая активная страница записывается в
в Location.state и служит "фоновым роутом".

#роутинг #документация #примерыкода
Программное создание конфига роутинга

https://stackblitz.com/github/remix-run/react-router/tree/main/examples/route-objects?file=src/App.tsx

Пример создания дерева роутов с помощью хука useRoutes как альтернатива использованию элементов Routes и Route.

#роутинг #документация #примерыкода
Повторный рендеринг и мемоизация в React

Статья (рус.): https://nuancesprog.ru/p/14850/

Вспоминаем о принципах рендеринга в React и способах его оптимизировать.

Повторный рендеринг обычно происходит из-за изменения пропсов или состояния компонента, при этом ререндерятся и все дочерние компоненты изменившегося родителя.

useRef

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

Подробнее про useRef

memo

Так как компоненты React - это обычные функции, их можно мемоизировать (сохранять результат работы для каждого набора входных параметров - пропсов). Для мемоизации используется HOC React.memo().

Подробнее про React.memo

useCallback

Если в компоненте создается какая-либо функция, например, коллбэк для обработки события, она будет создаваться заново при каждом рендере.

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

Такие функции следует оборачивать в хук useCallback, чтобы ссылка на функцию не изменялась.

Подробнее про useCallback

useMemo

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

В отличие от useCallback, useMemo сохраняет не саму функцию, а результат ее выполнения.

Подробнее про useMemo

Ленивая инициализация useState

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

Может быть полезно, если вычисление начального значения требует больших затрат.

Подробнее про ленивую инициализацию


#ссылки #оптимизация #хуки #hoc #паттерны
👍2
Управление состоянием

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

В ее рамках планирую:

- освежить в памяти хук useReducer и совместить его с хуком useContext для создания глобального состояния
- взглянуть на Redux (должно быть что-то очень похожее на предыдущую комбинацию)
- попробовать Redux Toolkit (набор инструментов для работы с Redux)
- разобрать альтернативные решения - Recoil, MobX и, может, что-то еще

#состояние #управлениесостоянием
👍3
Что такое стейт-менеджер

Заметка (рус.): https://gist.github.com/nodkz/41a5ee356581503033bd05104f5048bf

Интересный взгляд на управление состоянием с историческими параллелями и выделением самого главного.

Главный вывод

Стейт-Менеджер = Переменная + Функция (для измнения переменной) + паттерн Observable (чтобы подписаться на изменение переменной)

#управлениесостоянием #ссылки
👍1