Современный технический стек 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.
#ссылки #тестирование #стили #инструменты
Статья (англ.): 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.
#ссылки #тестирование #стили #инструменты
profy.dev
Most Popular React Tech Stack in 2023 (Based on Data)
The React ecosystem is huge so it's hard to keep an overview. Based on data here is a list of the most popular React libs used in 2022.
👍1
React Router. Навигация
Link
Роут указывается в пропе
По умолчанию смена роута происходит без перезагрузки страницы, но это поведение можно отменить с помощью пропа
NavLink
Навигационная ссылка с состоянием "активности". Если роут такой ссылки соответствует текущему роуту приложения, она помечается классом
Кроме того, в атрибут
И наконец, функцию можно передать в качестве дочернего элемента ссылки, чтобы рендерить динамический контент.
Примеры: https://codesandbox.io/s/navlink-react-junior-8g1xen
Кроме того, есть проп
Например, у нас есть ссылка, ведущая на роут
Navigate
Это способ управлять роутингом прямо из JSX-разметки, без JS-кода.
Если компонент
В документации в качестве примера приводится форма авторизации.
Мой вариант: https://codesandbox.io/s/navigate-react-junior-mrp48r?file=/src/pages/Login.js
У нас есть два роута, индексный с формой авторизации и
#роутинг #примерыкода
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
- происходит переход на страницу Личного кабинета.#роутинг #примерыкода
CodeSandbox
NavLink. React Junior - CodeSandbox
NavLink. React Junior by furrycat.web using react, react-dom, react-router-dom, react-scripts
React Router. Outlet
Компонент
https://codesandbox.io/s/outlet-react-junior-d08y8s?file=/src/App.js
Например, есть роут
Чтобы дочерние роуты выводились, нужно вставить
Контекст
Родительский компонент может передавать в дочерние роуты какие-либо данные через проп
Чтобы получить эти данные в дочернем компоненте, нужно использовать хук
#роутинг #примерыкода
Компонент
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
.#роутинг #примерыкода
CodeSandbox
Outlet. React Junior - CodeSandbox
Outlet. React Junior by furrycat.web using react, react-dom, react-router-dom, react-scripts, styled-components
React Router. Вспомогательные функции
Помимо рассмотренных компонентов и хуков, в пакете React Router есть еще ряд вспомогательных функций, которые используются для матчинга роутов и текущего урла, рендера активного роута и т.д. Они используются под капотом, но при необходимости, можно использовать их напрямую.
Их можно найти в документации на страничке с описанием API: https://reactrouter.com/docs/en/v6/api#api-reference
Если при дальнейшем изучении что-то из этого понадобится, то мы сюда вернемся.
#документация #роутинг
Помимо рассмотренных компонентов и хуков, в пакете React Router есть еще ряд вспомогательных функций, которые используются для матчинга роутов и текущего урла, рендера активного роута и т.д. Они используются под капотом, но при необходимости, можно использовать их напрямую.
Их можно найти в документации на страничке с описанием API: https://reactrouter.com/docs/en/v6/api#api-reference
Если при дальнейшем изучении что-то из этого понадобится, то мы сюда вернемся.
#документация #роутинг
Reactrouter
API Reference v6.3.0
React Router. Глубокое погружение
React Router сам по себе очень прост в использовании и можно особенно не заморачиваться для того, чтобы сделать нормально работающее приложение с маршрутизацией. Но под капотом у него происходит много сложных вещей.
В документации есть отдельный раздел Основные концепции для более подробного изучения React Router. Посмотрим на него одним глазом.
Прежде всего здесь приведены определения для всех терминов (Location, History Stack, Match и пр.): . Полезно начать именно с них, чтобы правильно воспринимать информацию.
Основные составляющие процесса маршрутизации:
- подписка и манипуляции с History Stack (история навигации пользователя)
- матчинг (сопоставление) урла и роутов
- рендеринг активных роутов
История навигации
В браузере есть объект
React Router позволяет изменять историю навигации программно, без перезагрузок страницы и отправки запросов на сервер. Он использует собственный объект history, чтобы отслеживать все изменения.
Для представления текущего урла (
Для измененения истории навигации предназначены компоненты
Для доступа к текущему урлу и его параметрам - хуки
Сопоставление роутов
В начале работы React Router составляет конфиг роутинга (route config), который по сути представляет собой просто дерево роутов, созданных с помощью
Создать такой конфиг можно программно с помощью хука
Текущий урл сравнивается со всеми существующими роутами, чтобы найти подходящие. Для каждого подходящего роута создается объет match с информацией о роуте, а также значениями динамических параметров, если они есть.
Так как роуты могут быть вложенными, совпасть может целое дерево роутов. В этом случае создается массив matches, где каждый вложенный роут представлен отдельным элементом.
Роуты без путей
Для некоторых роутов не указывается проп
Рендеринг
Первый роут из массива
Компонент
Общая схема работы
1. Мы пишем код приложения с компонентами
2.
3.
4. Вы вручную рендерите остальные совпавшие вложенные роуты, используя в нужных местах родительских компонентов
5. Пользователь кликает по компоненту
6.
7. Объект history изменяет урл и оповещает
8.
#документация #роутинг #подкапотом
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
Структура приложения
Есть открытая страница
Создаем три роута (
Контекст для хранения состояния
Для хранения состояния авторизации используется контекст
Контекст содержит актуальное состояние, а также методы для авторизации и разлогинивания.
Все приложение оборачивается в
Компонент-обертка для компонентов с закрытым доступом
Создаем вспомогательный компонент
Этот компонент получает доступ к контексту (через хук
У компонента
Кроме того, есть атрибут
Форма авторизации
Когда пользователь заполняет и отправляет форму, компонент
#документация #роутинг #примерыкода
Пример из документации: 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
, или просто на главную страницу приложения.#документация #роутинг #примерыкода
StackBlitz
React-router Auth Example - StackBlitz
Run official live example code for React-router Auth, created by Remix Run on StackBlitz
React Router. Кастомная ссылка
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/custom-link?file=src/App.tsx
Пример создания собственного аналога
Для определения совпадения с текущим роутом используется хук
#документация #роутинг #примерыкода
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/custom-link?file=src/App.tsx
Пример создания собственного аналога
NavLink
- ссылки на роут, которая знает, когда она активна.Для определения совпадения с текущим роутом используется хук
useMatch
.#документация #роутинг #примерыкода
StackBlitz
React-router Custom Link Example - StackBlitz
Run official live example code for React-router Custom Link, created by Remix Run on StackBlitz
Глубокое погружение в код React. Часть 1. Вводная
Первая часть из серии статей, посвященных разбору кодовой базы React (англ.): https://dev.to/fromaline/deep-dive-into-react-codebase-ep1-prerequisites-33ak
Это вводная часть, которая рассказывает:
- почему React вообще появился (потому что команда разработчиков из Facebook создала сложное приложение с динамическими данными и не смогла справиться с каскадными изменениями интерфейса)
- какова основная идея React (у тебя есть код, который описывает, что должно делать приложение с определенным набором данных. Если данные изменятся, нужно просто перезапустить этот же самый код)
- и как устроен монорепозиторий React (ядро React Core, несколько рендереров для разных сред выполнения и согласователь Fiber Reconciler)
#ссылки #подкапотом
Первая часть из серии статей, посвященных разбору кодовой базы React (англ.): https://dev.to/fromaline/deep-dive-into-react-codebase-ep1-prerequisites-33ak
Это вводная часть, которая рассказывает:
- почему React вообще появился (потому что команда разработчиков из Facebook создала сложное приложение с динамическими данными и не смогла справиться с каскадными изменениями интерфейса)
- какова основная идея React (у тебя есть код, который описывает, что должно делать приложение с определенным набором данных. Если данные изменятся, нужно просто перезапустить этот же самый код)
- и как устроен монорепозиторий React (ядро React Core, несколько рендереров для разных сред выполнения и согласователь Fiber Reconciler)
#ссылки #подкапотом
DEV Community
Deep dive into React codebase [EP1: Prerequisites]
Preface My last article about the obscured history behind Hyperscript was warmly received,...
React Router. Lazy loading
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/lazy-loading?file=src/App.tsx
Пример ленивой загрузки компонентов для роутов. Ничего особенного, обычные "ленивые компоненты" с использованием
#документация #роутинг #примерыкода #ленивыекомпоненты
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/lazy-loading?file=src/App.tsx
Пример ленивой загрузки компонентов для роутов. Ничего особенного, обычные "ленивые компоненты" с использованием
React.lazy
для загрузки и React.Suspense
для отображения с фоллбэком.#документация #роутинг #примерыкода #ленивыекомпоненты
Stackblitz
React-router Lazy Loading Example - StackBlitz
Run official live example code for React-router Lazy Loading, created by Remix Run on StackBlitz
Location State
В примере с аутентификацией использовалось некое "состояние Location", чтобы сохранить, на какую страницу пользователь хотел попасть, когда открылась форма авторизации. Разберемся с ним чуть подробнее.
У объекта
Однако в сигнатуре этого метода три параметра, и урл - последний из них и необязательный. Первым идет
Получить текущее состояние можно из
React Router позволяет удобно пользоваться этой фишкой прямо из объекта
Чтобы установить state для 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
.Кейсы для использования:
- сохранение предыдущей локации для последующего перенаправления
- отправка данных (обычно урезанных, самых необходимых) для быстрого отображения на новой локации, пока основные данные загружаются
#роутинг #документация #паттерны
Telegram
React Junior
React Router. Аутентификация
Пример из документации: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx
Структура приложения
Есть открытая страница PublicPage, доступная по пути /. И есть закрытая страница ProtectedPage…
Пример из документации: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx
Структура приложения
Есть открытая страница PublicPage, доступная по пути /. И есть закрытая страница ProtectedPage…
React Router. Модальное окно
Пример реализации модального окна с помощью роутера: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src/App.tsx
В приложении есть два контейнера
Когда модальное окно открывается, текущая активная страница записывается в
в Location.state и служит "фоновым роутом".
#роутинг #документация #примерыкода
Пример реализации модального окна с помощью роутера: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src/App.tsx
В приложении есть два контейнера
Routes
, так что модальное окно может отображаться одновременно с основной страницей. При этом одна ветка роутов использует текущее значение location
, а для другой оно задается вручную с помощью пропа location
.Когда модальное окно открывается, текущая активная страница записывается в
в Location.state и служит "фоновым роутом".
#роутинг #документация #примерыкода
StackBlitz
React-router Modal Example - StackBlitz
Run official live example code for React-router Modal, created by Remix Run on StackBlitz
Программное создание конфига роутинга
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/route-objects?file=src/App.tsx
Пример создания дерева роутов с помощью хука
#роутинг #документация #примерыкода
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/route-objects?file=src/App.tsx
Пример создания дерева роутов с помощью хука
useRoutes
как альтернатива использованию элементов Routes
и Route
.#роутинг #документация #примерыкода
Stackblitz
React-router Route Objects Example - StackBlitz
Run official live example code for React-router Route Objects, created by Remix Run on StackBlitz
Повторный рендеринг и мемоизация в React
Статья (рус.): https://nuancesprog.ru/p/14850/
Вспоминаем о принципах рендеринга в React и способах его оптимизировать.
Повторный рендеринг обычно происходит из-за изменения пропсов или состояния компонента, при этом ререндерятся и все дочерние компоненты изменившегося родителя.
useRef
Обычно для изменяющихся значений используют
Подробнее про useRef
memo
Так как компоненты React - это обычные функции, их можно мемоизировать (сохранять результат работы для каждого набора входных параметров - пропсов). Для мемоизации используется HOC
Подробнее про React.memo
useCallback
Если в компоненте создается какая-либо функция, например, коллбэк для обработки события, она будет создаваться заново при каждом рендере.
Если вы используете мемоизированный компонент, но передаете в него такую изменяющуюся функцию, то все труды по мемоизации пройдут напрасно.
Такие функции следует оборачивать в хук
Подробнее про useCallback
useMemo
Хук
В отличие от
Подробнее про useMemo
Ленивая инициализация useState
В хук
Может быть полезно, если вычисление начального значения требует больших затрат.
Подробнее про ленивую инициализацию
#ссылки #оптимизация #хуки #hoc #паттерны
Статья (рус.): 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 #паттерны
NOP::Nuances of programming
Повторный рендеринг и мемоизация в React
Разработчики React прикладывают максимум усилий, чтобы увеличить производительность своего продукта. Сегодня мы рассмотрим основные инструменты оптимизации эффективности этой библиотеки.
👍2
Управление состоянием
Разобравшись более-менее с маршрутизацией (значимых альтернатив React Router вроде не нашлось), переходим к новой большой (очень большой) теме: управление глобальным состоянием приложения.
В ее рамках планирую:
- освежить в памяти хук
- взглянуть на Redux (должно быть что-то очень похожее на предыдущую комбинацию)
- попробовать Redux Toolkit (набор инструментов для работы с Redux)
- разобрать альтернативные решения - Recoil, MobX и, может, что-то еще
#состояние #управлениесостоянием
Разобравшись более-менее с маршрутизацией (значимых альтернатив React Router вроде не нашлось), переходим к новой большой (очень большой) теме: управление глобальным состоянием приложения.
В ее рамках планирую:
- освежить в памяти хук
useReducer
и совместить его с хуком useContext
для создания глобального состояния- взглянуть на Redux (должно быть что-то очень похожее на предыдущую комбинацию)
- попробовать Redux Toolkit (набор инструментов для работы с Redux)
- разобрать альтернативные решения - Recoil, MobX и, может, что-то еще
#состояние #управлениесостоянием
👍3
Что такое стейт-менеджер
Заметка (рус.): https://gist.github.com/nodkz/41a5ee356581503033bd05104f5048bf
Интересный взгляд на управление состоянием с историческими параллелями и выделением самого главного.
Главный вывод
Стейт-Менеджер = Переменная + Функция (для измнения переменной) + паттерн Observable (чтобы подписаться на изменение переменной)
#управлениесостоянием #ссылки
Заметка (рус.): https://gist.github.com/nodkz/41a5ee356581503033bd05104f5048bf
Интересный взгляд на управление состоянием с историческими параллелями и выделением самого главного.
Главный вывод
Стейт-Менеджер = Переменная + Функция (для измнения переменной) + паттерн Observable (чтобы подписаться на изменение переменной)
#управлениесостоянием #ссылки
Gist
Что такое Стейт Менеджер для вас?
Что такое Стейт Менеджер для вас? GitHub Gist: instantly share code, notes, and snippets.
👍1
Почему React Context - это не инструмент для "управления состоянием" (и почему он не может заменить Redux)
Большая статья с подробным сравнением React Context и Redux (англ.): https://blog.isquaredsoftware.com/2021/01/context-redux-differences/
Основная идея заключается в том, что контекст сам по себе не имеет никакого отношения к управлению состоянием, а является только механизмом доставки данных без утомительного проброса пропсов. В некотором смысле это паттерн Внедрение зависимостей (Dependency Injection).
Контекст в комбинации с хуком
Redux же - это полноценный менеджер состояния, специально созданный для этой задачи. Он позволяет работать с большими и сложными состояниями, хорошо масштабируется и дает массу дополнительных плюшек.
React-Redux под капотом также использует контекст, но пробрасывает не сами данные, а собственно объект хранилища. То есть использует контекст для внедрения зависимостей.
Статья написана очень подробно и понятно, рекомендую 🙂
#ссылки #управлениесостоянием #redux #контекст
Большая статья с подробным сравнением React Context и Redux (англ.): https://blog.isquaredsoftware.com/2021/01/context-redux-differences/
Основная идея заключается в том, что контекст сам по себе не имеет никакого отношения к управлению состоянием, а является только механизмом доставки данных без утомительного проброса пропсов. В некотором смысле это паттерн Внедрение зависимостей (Dependency Injection).
Контекст в комбинации с хуком
useReducer
- это уже что-то более похожее на state managment, но совсем на минималках. Тут уже можно работать с более-менее сложным состоянием. Это может быть хорошим решением для небольших проектов. Основная проблема - невозможность разделения данных. Если компонент подписывается на изменением состояния, то он будет перерендерен при любом его изменении, даже если изменилась часть, которая этот конкретный компонент не интересует. Конечно, можно создавать отдельные контексты для разных данных, но тут потенциал масштабирования очень маленький.Redux же - это полноценный менеджер состояния, специально созданный для этой задачи. Он позволяет работать с большими и сложными состояниями, хорошо масштабируется и дает массу дополнительных плюшек.
React-Redux под капотом также использует контекст, но пробрасывает не сами данные, а собственно объект хранилища. То есть использует контекст для внедрения зависимостей.
Статья написана очень подробно и понятно, рекомендую 🙂
#ссылки #управлениесостоянием #redux #контекст
Mark's Dev Blog
Blogged Answers: Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)
Definitive answers and clarification on the purpose and use cases for Context and Redux
Вспоминаем useReducer
Хук
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в
Но что если логика расчета нового
Для этого у нас есть хук
Тут не нужно сразу рассчитывать новое значение, достаточно лишь указать, какое действие произошло. Мы переходим на новую, более декларативную, концепцию - экшены.
Представим простейшую ситуацию: у нас есть некий счетчик. При нажатии на кнопку +1 мы хотим увеличить его значение на единицу.
С
С
Это действие передается в редьсер, который уже вычисляет новое значие
В общем, ничего сложного, просто небольшой сдвиг мировоззрения. Две новые концепции - инкапсуляция логики изменения состояния в функции редьюсере и экшены - типа команды для изменения состояния.
#хуки #управлениесостоянием #состояние
Хук
useState
работает очень просто:
const [value, setValue] = useState()
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в
value
, и передаем это в setValue
.Но что если логика расчета нового
value
сложнее, чем прибавить единицу к предыдущему значению? Если есть несколько причин для изменения value
и хотелось бы контролировать их все в одном месте, иначе отлаживать будет невозможно?Для этого у нас есть хук
useReducer
, который по сути является более продвинутым useState
. Говорили про него здесь. Он позволяет инкапсулировать всю логику изменения состояния в одной функции - редьюсере.
const [value, dispatch] = useReducer(reducer, initialValue)
Тут не нужно сразу рассчитывать новое значение, достаточно лишь указать, какое действие произошло. Мы переходим на новую, более декларативную, концепцию - экшены.
Представим простейшую ситуацию: у нас есть некий счетчик. При нажатии на кнопку +1 мы хотим увеличить его значение на единицу.
С
useState
это выглядит так:
setValue(function(currentValue) {
return currentValue + 1;
})
С
useReducer
мы передаем не значение, а действие:
dispatch({ type: 'increment' })
Это действие передается в редьсер, который уже вычисляет новое значие
value
, исходя из типа экшена.В общем, ничего сложного, просто небольшой сдвиг мировоззрения. Две новые концепции - инкапсуляция логики изменения состояния в функции редьюсере и экшены - типа команды для изменения состояния.
#хуки #управлениесостоянием #состояние
Telegram
React Junior
useReducer
Альтернатива useState для более сложной логики состояния.
Сигнатура: const [state, dispatch] = useReducer(reducer, initialArg, init);
- reducer - функция с сигнатурой (state, action) => newState, которая должна вернуть актуальное состояние…
Альтернатива useState для более сложной логики состояния.
Сигнатура: const [state, dispatch] = useReducer(reducer, initialArg, init);
- reducer - функция с сигнатурой (state, action) => newState, которая должна вернуть актуальное состояние…
Очень простой пример использования
https://codesandbox.io/s/usereducer-react-junior-5x89x8?file=/src/App.js
Редьюсер и начальное состояние вынесены в отдельный файл state.js. Функция-редьюсер получает экшен, смотрит на его тип и производит все необходимые изменения, возвращает обновленное состояние.
Экшены отправляются с помощью функции
У нас есть четыре типа экшенов, которые понимает редьюсер: increment, decrement, add (с полезной нагрузкой, параметром, который определяет, сколько именно нужно прибавить к счетчику) и reset.
#примерыкода #хуки #состояние #управлениесостоянием
useReducer
https://codesandbox.io/s/usereducer-react-junior-5x89x8?file=/src/App.js
Редьюсер и начальное состояние вынесены в отдельный файл state.js. Функция-редьюсер получает экшен, смотрит на его тип и производит все необходимые изменения, возвращает обновленное состояние.
Экшены отправляются с помощью функции
dispatch
, которую возвращает хук.У нас есть четыре типа экшенов, которые понимает редьюсер: increment, decrement, add (с полезной нагрузкой, параметром, который определяет, сколько именно нужно прибавить к счетчику) и reset.
#примерыкода #хуки #состояние #управлениесостоянием
CodeSandbox
useReducer. React Junior - CodeSandbox
useReducer. React Junior by furrycat.web using react, react-dom, react-scripts
useReducer + useContext
Реализуем управление состоянием с помощью только хуков React (комбинация useReducer + useContext), без использования сторонних библиотек.
https://codesandbox.io/s/usereducer-usecontext-react-junior-um0bsr?file=/src/App.js
*Пример условный, упрощенный и неоптимизированный, только для демонстрации работы с состоянием
Мы имеем тут какой-то личный финансовый кабинет. У пользователя есть баланс средств, баланс бонусов (10 бонусов начисляется, если пользователь вносит больше 1000), а также возможность пополнить баланс или снять деньги.
Состояние
Все состояние хранится в одном месте (файл state.js). Там же определен редьюсер, который понимает экшены двух типов
Контекст
Контекст используется, чтобы передавать состояние приложения в любой заинтересованный компонент без проброса пропсов. Все кейсы использования контекста (компонент-провайдер и хук для доступа к контексту) собраны в файле depositeContext.js.
Схема работы
1. В корневом компоненте
2. Создаем отдельный контекст с помощью хука
3. В заинтересованных компонентах получаем доступ к контексту (и функции
#хуки #управлениесостоянием #состояние #примерыкода
Реализуем управление состоянием с помощью только хуков React (комбинация useReducer + useContext), без использования сторонних библиотек.
https://codesandbox.io/s/usereducer-usecontext-react-junior-um0bsr?file=/src/App.js
*Пример условный, упрощенный и неоптимизированный, только для демонстрации работы с состоянием
Мы имеем тут какой-то личный финансовый кабинет. У пользователя есть баланс средств, баланс бонусов (10 бонусов начисляется, если пользователь вносит больше 1000), а также возможность пополнить баланс или снять деньги.
Состояние
Все состояние хранится в одном месте (файл state.js). Там же определен редьюсер, который понимает экшены двух типов
put
(пополнение) и withdraw
(снятие). Редьюсер меняет баланс, следит за начислением бонусов, сохраняет историю операций. Кроме того, в состояние добавлено поле error
- какая-либо ошибка при выполнении операций.Контекст
Контекст используется, чтобы передавать состояние приложения в любой заинтересованный компонент без проброса пропсов. Все кейсы использования контекста (компонент-провайдер и хук для доступа к контексту) собраны в файле depositeContext.js.
Схема работы
1. В корневом компоненте
App
создаем состояние с помощью хука useReducer
, получаем функцию dispatch
для управления состоянием.2. Создаем отдельный контекст с помощью хука
useContext
, оборачиваем все приложение в провайдер этого контекста. В контекст добавляем и само состояние, и функцию dispatch
.3. В заинтересованных компонентах получаем доступ к контексту (и функции
dispatch
) с помощью кастомного хука useDepositeContext
(под капотом обычный useContext
). #хуки #управлениесостоянием #состояние #примерыкода
Telegram
React Junior
Вспоминаем useReducer
Хук useState работает очень просто:
const [value, setValue] = useState()
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в value, и передаем это в setValue.
Но что если…
Хук useState работает очень просто:
const [value, setValue] = useState()
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в value, и передаем это в setValue.
Но что если…
Задача: при внесении большой суммы на счет (больше тысячи) нужно добавлять клиенту бонусы. Где должна находиться эта логика (проверка суммы)?
Anonymous Poll
65%
В редьюсере
20%
В компоненте
15%
Где-то еще (где?)