Список тегов для более удобного поиска постов
👉 Основные понятия
#компоненты
#jsx
#жизненныйциклкомпонента
#виртуальныйdom
#состояние
#обработкасобытий
#потокданных
#ключи
#формы
#рефы
#hoc
#рендерпропсы
#контекст
#порталы
#хуки
#concurrentmode
👉 Управление состоянием
#управлениесостоянием
#redux
#mobx
#recoil
👉 Работа с ошибками
#обработкаошибок
#предохранители
#отладка
#проверкатипов
#typescript
#строгийрежим
👉 Оптимизация
#оптимизация
#profiler
#ленивыекомпоненты
#purecomponent
👉 Тестирование
#тестирование
#jest
#testinglibrary
👉 Серверный рендеринг
#серверныйрендеринг
👉 Стилизация
#стили
#styledcomponents
#jss
#radium
#shadowdom
👉 Распространенные задачи
#валидацияформ
#роутинг
#обменданными
#rtkquery
👉 Прочее
#документация - материалы из официальной документации
#ссылки - полезные ссылки
#началоработы - базовые знания, необходимые для начала работы
#паттерны - хорошие практики работы с React
#примерыкода - реальные примеры кода для изучения
#важно - моменты, на которые нужно обратить внимание
#ошибки - частые ошибки новичков в React
#вопросы
#подкапотом - невидимая часть React
#подключение - подключение React, а также дополнительных пакетов
#инструменты - полезные инструменты для разработки
#доступность
#проект - организация файлов и другие вопросы уровня целого проекта
#api
#безопасность
#отложено - аспекты уже пройденных тем, временно отложенные
👉 Основные понятия
#компоненты
#jsx
#жизненныйциклкомпонента
#виртуальныйdom
#состояние
#обработкасобытий
#потокданных
#ключи
#формы
#рефы
#hoc
#рендерпропсы
#контекст
#порталы
#хуки
#concurrentmode
👉 Управление состоянием
#управлениесостоянием
#redux
#mobx
#recoil
👉 Работа с ошибками
#обработкаошибок
#предохранители
#отладка
#проверкатипов
#typescript
#строгийрежим
👉 Оптимизация
#оптимизация
#profiler
#ленивыекомпоненты
#purecomponent
👉 Тестирование
#тестирование
#jest
#testinglibrary
👉 Серверный рендеринг
#серверныйрендеринг
👉 Стилизация
#стили
#styledcomponents
#jss
#radium
#shadowdom
👉 Распространенные задачи
#валидацияформ
#роутинг
#обменданными
#rtkquery
👉 Прочее
#документация - материалы из официальной документации
#ссылки - полезные ссылки
#началоработы - базовые знания, необходимые для начала работы
#паттерны - хорошие практики работы с React
#примерыкода - реальные примеры кода для изучения
#важно - моменты, на которые нужно обратить внимание
#ошибки - частые ошибки новичков в React
#вопросы
#подкапотом - невидимая часть React
#подключение - подключение React, а также дополнительных пакетов
#инструменты - полезные инструменты для разработки
#доступность
#проект - организация файлов и другие вопросы уровня целого проекта
#api
#безопасность
#отложено - аспекты уже пройденных тем, временно отложенные
Redux Essentials 16. RTK Query. Создание слайса
RTK Query - это еще один уровень абстракции над абстракциями Redux, позволяющий инкапсулировать работу с API: методы получения/обновления/удаления данных, состояние выполнения запроса, синхронизация состояния на клиенте и на сервере, оптимистичные обновления клиентского стейта, кеширование и т.д.
При этом все, что связано с API, выносится в отдельный слайс. Если у нас есть в приложении несколько разных запросов к одному и тому же серверу (работа со статьями, уведомлениями) - все это будет в отдельном слайсе, и методы, и сами данные.
RTK Query предоставляет две основные функции:
-
-
Они находятся в пакете
Есть еще
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Создание и добавление слайса
Слайс для API создаем в файле
Важно правильно подключить новый слайс в методе
Сам сгенерированный редьюсер находится в
Кроме того, нужно добавить миддлвар
#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
RTK Query - это еще один уровень абстракции над абстракциями Redux, позволяющий инкапсулировать работу с API: методы получения/обновления/удаления данных, состояние выполнения запроса, синхронизация состояния на клиенте и на сервере, оптимистичные обновления клиентского стейта, кеширование и т.д.
При этом все, что связано с API, выносится в отдельный слайс. Если у нас есть в приложении несколько разных запросов к одному и тому же серверу (работа со статьями, уведомлениями) - все это будет в отдельном слайсе, и методы, и сами данные.
RTK Query предоставляет две основные функции:
-
createApi
для создания слайса;-
fetchBaseQuery
- небольшая утилитарная обертка вокруг метода fetch
Они находятся в пакете
@reduxjs/toolkit/query
- это базовая версия библиотеки.Есть еще
@reduxjs/toolkit/query/react
- те же самые функции специально для React. Они автоматически генерируют хуки на базе созданных методов. Мы будем использовать именно этот пакет.Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Создание и добавление слайса
Слайс для API создаем в файле
features/api/apiSlice.js
. export const apiSlice = createApi({Помимо прочих настроек метод
reducerPath: 'api',
// ...
})
createApi
принимает поле reducerPath
, в котором нужно указать, где именно в общем state
будут лежать данные, полученные из API. По умолчанию значение этого поля api
- то есть данные нужно будет извлекать из state.api
.Важно правильно подключить новый слайс в методе
configureStore
. Чтобы не ошибиться, используем в качестве названия поля свойство apiSlice.reducerPath
.Сам сгенерированный редьюсер находится в
apiSlice.reducer
.Кроме того, нужно добавить миддлвар
apiSlice.middlewar
для кеширования данных. Сделать это можно в методе configureStore
в настройке middleware
. Она принимает функцию, которой в качестве аргумента передается метод getDefaultMiddleware
. Вернуть нужно обновленный массив миддлваров, поэтому вызываем этот метод и добавляем в него новый миддлвар.#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
👍4
Redux Essentials 16. RTK Query. Выполнение запросов
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
baseQuery
Основная (обязательная) настройка в методе
В качестве такой функции можно использовать встроенную
Внутри одного API-слайса предполагается, что все запросы осуществляются к одному серверу (это необязательно). Так что здесь можно установить базовые настройки запроса, например,
Так как в моем проекте реального API нет, придется использовать кастомную функцию
Вместо этого можно, например, реализовать запросы с помощью библиотеки axios.
#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
baseQuery
Основная (обязательная) настройка в методе
createApi
- это baseQuery
. Это функция, которая непосредственно выполняет запросы. В качестве такой функции можно использовать встроенную
fetchBaseQuery
- обертку над стандартным методом fetch
.Внутри одного API-слайса предполагается, что все запросы осуществляются к одному серверу (это необязательно). Так что здесь можно установить базовые настройки запроса, например,
baseUrl
- фрагмент урла, с которого начинаются все эндпоинты.const apiSlice = createApi({Но можно использовать и собственную функцию для выполнения запросов. Важно, чтобы она возвращала ответ в нужном формате. Полученные данные должны находиться в поле
// ...
baseQuery: fetchBaseQuery({ baseUrl: '/fakeApi' })
})
data
, а ошибка, если она есть, в поле error
. Так как в моем проекте реального API нет, придется использовать кастомную функцию
customFetchBaseQuery
, которая вместо настоящих запросов просто обращается к модулю fakeApi
.Вместо этого можно, например, реализовать запросы с помощью библиотеки axios.
#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. RTK Query. React Junior - CodeSandbox
Redux Essentials. RTK Query. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍2
Redux Essentials 16. RTK Query. Эндпоинты
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Теперь самое интересное - добавление эндпоинтов для реальной работы с данными.
Поле
У билдера есть метод
-
-
Начнем с добавления эндпоинта
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Теперь самое интересное - добавление эндпоинтов для реальной работы с данными.
Поле
endpoints
в настройках метода createApi
- это функция, которая в качестве аргумента принимает builder
, а вернуть должна коллекцию (объект) эндпоинтов. У билдера есть метод
query
, который принимает объект настроек запроса. Настроек очень много, но можно пока обойтись основными:-
query
- функция, которая возвращает урл запроса. Этот урл будет присоединен к baseUrl
, если он был указан ранее.-
transformResponse
- функция для обработки ответа, если он не соответствует ожидаемому формату.Начнем с добавления эндпоинта
getPosts
для получения списка постов.const apiSlice = createApi({#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
// ...
endpoints: function(builder) {
return {
getPosts: builder.query({
query: function() { return "/posts" },
transformResponse: function(response) { return response.data }
})
}
}
})
CodeSandbox
Redux Essentials. RTK Query. React Junior - CodeSandbox
Redux Essentials. RTK Query. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍2
Redux Essentials 16. RTK Query. Использование данных
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/posts/PostsList.js
У нас есть функция для выполнения запросов, описанный эндпоинт, осталось только получить данные (список статей) в компоненте
Хуки запросов
RTK Query (в React-версии - @reduxjs/toolkit/query/react) автоматически генерирует хук для каждого созданного эндпоинта. Название хука формируется по шаблону
👉
Кроме запросов еще есть мутации, но мы до них пока не дошли.
Таким образом, для эндпоинта
Использование хуков в компоненте
При использовании этот хук возвращает массу полезных данных:
-
#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/posts/PostsList.js
У нас есть функция для выполнения запросов, описанный эндпоинт, осталось только получить данные (список статей) в компоненте
PostsList
и отобразить их.Хуки запросов
RTK Query (в React-версии - @reduxjs/toolkit/query/react) автоматически генерирует хук для каждого созданного эндпоинта. Название хука формируется по шаблону
👉
use
+ имя эндпоинта + query
query
добавляется для запросов, созданных через builder.query
. Кроме запросов еще есть мутации, но мы до них пока не дошли.
Таким образом, для эндпоинта
getPosts
у нас есть хук apiSlice.useGetPostsQuery
.Использование хуков в компоненте
При использовании этот хук возвращает массу полезных данных:
-
data
- собственно данные из api
- isLoading
- isSuccess
- isError
- error
С ними можно построить интерфейс компонента для всех состояний запроса.#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
👍3👏1
Redux Essentials 16. RTK Query. Потерянный функционал
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/posts/PostsList.js
Перейдя на новый способ работы с данными через RTK Query, мы потеряли реализованный ранее функционал сортировки статей по дате. Документация обещает позже рассказать, как это делать правильно, а пока ограничимся простой сортировкой прямо в компоненте.
Используем useMemo, чтобы сортировка происходила только при изменении массива
#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/posts/PostsList.js
Перейдя на новый способ работы с данными через RTK Query, мы потеряли реализованный ранее функционал сортировки статей по дате. Документация обещает позже рассказать, как это делать правильно, а пока ограничимся простой сортировкой прямо в компоненте.
Используем useMemo, чтобы сортировка происходила только при изменении массива
posts
.#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
👍3
Redux Essentials 17. RTK Query. Страница статьи
Так как список постов мигрировал в API-слайс, перестала работать страница отдельного поста.
Чтобы получить данные одной статьи, можно, например, получать весь список с помощью
https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Кеширование запросов
Посмотрим, что там с кешированием: https://lced2j.csb.app/
Открываем главную страницу:
- выполняется экшен
- заглянем в State: в
Теперь переходим на страницу поста:
- снова выполняются экшены
- в
Если теперь вернуться на главную и снова зайти на страницу этой же статьи, мы увидим экшен
#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
Так как список постов мигрировал в API-слайс, перестала работать страница отдельного поста.
Чтобы получить данные одной статьи, можно, например, получать весь список с помощью
useGetPostsQuery
, а затем фильтровать его. Хук даже принимает объект настроек с методом selectFromResult
:const { post, isLoading } = useGetPostsQuery(null, {Но лучше добавить отдельный эндпоинт
selectFromResult: function(result) {
if (result.isLoading) {
return {
isLoading: true
}
}
if (result.isSuccess) {
const post = result.data.find(function(post) {
return post.id === id;
});
return { post }
}
return {
post: null
}
}
})
getPost
для получения одной статьи и использовать хук useGetPostQuery
.https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Кеширование запросов
Посмотрим, что там с кешированием: https://lced2j.csb.app/
Открываем главную страницу:
- выполняется экшен
api/executeQuery/pending
, а затем api/executeQuery/fulfilled
. Это запрашивается список статей.- заглянем в State: в
api.queries
появилось поле getPosts(undefined)
, а в нем данные. Это кеш для запроса к эндпоинту getPosts
без параметров.Теперь переходим на страницу поста:
- снова выполняются экшены
api/executeQuery/pending
и api/executeQuery/fulfilled
. Это запрашиваются данные поста.- в
state.api.queries
появилось новое поле getPost(E2-wMYL5CESZ6hDRMqsf2)
, в котором сохранены результаты запроса.Если теперь вернуться на главную и снова зайти на страницу этой же статьи, мы увидим экшен
api/executeQuery/rejected
. Данные для запроса к этому эндпоинту с этим параметром уже закешированы, поэтому заново запрос не осуществляется.#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
Redux Essentials 18. RTK Query. Обновление данных
Запрашивать данные из API мы умеем, теперь нужно научиться их отправлять. Для этого в RTK Query существуют мутации.
https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Создание нового поста
Добавляем новый эндпоинт
Сгенерированный хук для этого эндпоинта будет называться
Использование хука мутации немного отличается от хука запроса. Он возвращает не один, а два элемента - функцию-триггер, вызов которой запускает хук, и объект с состоянием запроса.
Обновление списка постов
После создания нового поста нужно обновить список - по новой запросить его с сервера.
Можно, например, добавить кнопку, при нажатии на которую список будет обновляться (добавлена в компоненте
Используем для этого функцию
Инвалидация кеша
Заставлять пользователя вручную обновлять список при добавлении поста - неправильно. Лучше сделать это автоматически. Для этого нужно заставить RTK Query сбросить кеш запроса и выполнить его заново. Чтобы показать, какой именно кеш нужно сбросить, используются теги:
#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
Запрашивать данные из API мы умеем, теперь нужно научиться их отправлять. Для этого в RTK Query существуют мутации.
https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
Создание нового поста
Добавляем новый эндпоинт
addNewPost
для создания новой статьи. Вместо метода builder.query
используем builder.mutation
. Настройка query
будет немного посложнее, вместо простой строки с урлом она возвращает объект с настройками запроса: url
, method
, body
.Сгенерированный хук для этого эндпоинта будет называться
useAddNewPostMutation
.Использование хука мутации немного отличается от хука запроса. Он возвращает не один, а два элемента - функцию-триггер, вызов которой запускает хук, и объект с состоянием запроса.
const [ addNewPost, { isLoading }] = useAddNewPostMutation();В компоненте
AddPostForm
заменяем dispatch
на addNewPost
.Обновление списка постов
После создания нового поста нужно обновить список - по новой запросить его с сервера.
Можно, например, добавить кнопку, при нажатии на которую список будет обновляться (добавлена в компоненте
PostsList
).Используем для этого функцию
refetch
, которую возвращает хук useGetPostsQuery
:const { data, isFetching, isSuccess, isError, refetch } = useGetPostsQuery();Кроме того, нужно заменить флаг
isLoading
на isFetching
. Первый отображает состояние только самого первого запроса, а второй - любого обновления (и первого запроса, и последующих). Инвалидация кеша
Заставлять пользователя вручную обновлять список при добавлении поста - неправильно. Лучше сделать это автоматически. Для этого нужно заставить RTK Query сбросить кеш запроса и выполнить его заново. Чтобы показать, какой именно кеш нужно сбросить, используются теги:
const apiSlice = createApi({Сначала обозначаем используемые теги в массиве
// ...
tagTypes: ["Post"],
endpoints: function(builder) {
return {
getPosts: builder.query({
// ...
providesTags: ["Post"]
}),
addNewPost: builder.mutation({
// ...
invalidatesTags: ["Post"]
})
}
}
})
tagTypes
. Затем привязываем тег Post
к эндпоинту getPosts
с помощью providesTags
. И наконец инвалидируем кеш для тега Post
в мутации addNewPost
с помощью invalidatedTags
.#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
CodeSandbox
Redux Essentials. RTK Query. React Junior - CodeSandbox
Redux Essentials. RTK Query. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍2
Redux Essentials 19. RTK Query. Редактирование статьи
Технически редактироание статьи не сильно отличается от добавления новой.
https://codesandbox.io/s/redux-essentials-rtk-query-2-react-junior-5chi5e?file=/src/features/api/apiSlice.js
1. Создаем мутацию
3. Подключаем хук
Интересны тут два момента: кеширование данных между компонентами и инвалидация кеша только для нужного поста.
Кеширование
При открытии страницы поста мы запрашиваем данные для него (
Если уйти с этой страницы, RTK Query под капотом удалит эту подписку. А также запустит таймер. Если в течение определенного времени (по умолчанию 60 секунд) на тот же самый запрос никто не подпишется, то данные тоже удалятся, так как они не нужны приложению.
Отписку и удаление данных можно наблюдать в панели разработчика (вкладка Redux) - экшены
Проект: https://5chi5e.csb.app/
Но если со страницы просмотра поста перейти на страницу его редактирования, то сразу после отписки будет произведена новая подписка. Поэтому для формы редактирования будут использоваться те же самые данные, которые были получены для страницы просмотра.
Инвалидация кеша для отдельного поста
После редактирования поста мы сразу переходим на его страницу для просмотра, поэтому необходимо сбросить кеш запроса и получить обновленные данные. Кроме того, нужно сбросить кеш запроса списка постов.
В прошлый раз мы использовали теги для инвалидации кеша. Можно попробовать добавить тег 'Post' к запросу
Необходимо "уточнить" тег, добавить в него параметры, чтобы он указывал на конкретную сущность. Вместо строки 'Post' мы можем указать объект
Поле
Поле
Технически редактироание статьи не сильно отличается от добавления новой.
https://codesandbox.io/s/redux-essentials-rtk-query-2-react-junior-5chi5e?file=/src/features/api/apiSlice.js
1. Создаем мутацию
editPost
, экспортируем новый хук useEditPostMutation
.endpoints: {2. В компоненте
//...
editPost: builder.mutation({
query: post => ({
url: '',
method: 'PATCH',
body: post
})
})
}
EditPostForm
сначала получаем данные поста (хук useGetPostQuery
), чтобы подставить их в форму. 3. Подключаем хук
useEditPostMutation
, получаем из него функцию updatePost
.const { data: post } = useGetPostQuery(postId);4. При отправке формы вызываем
const [updatePost, { isLoading }] = useEditPostMutation();
updatePost
с новыми данными.Интересны тут два момента: кеширование данных между компонентами и инвалидация кеша только для нужного поста.
Кеширование
При открытии страницы поста мы запрашиваем данные для него (
useGetPostQuery
), другими словами "подписываемся" на результаты запроса getPost(post_id)
. Если уйти с этой страницы, RTK Query под капотом удалит эту подписку. А также запустит таймер. Если в течение определенного времени (по умолчанию 60 секунд) на тот же самый запрос никто не подпишется, то данные тоже удалятся, так как они не нужны приложению.
Отписку и удаление данных можно наблюдать в панели разработчика (вкладка Redux) - экшены
api/subscriptions/unsubscribeQueryResult
и api/queries/removeQueryResult
.Проект: https://5chi5e.csb.app/
Но если со страницы просмотра поста перейти на страницу его редактирования, то сразу после отписки будет произведена новая подписка. Поэтому для формы редактирования будут использоваться те же самые данные, которые были получены для страницы просмотра.
Инвалидация кеша для отдельного поста
После редактирования поста мы сразу переходим на его страницу для просмотра, поэтому необходимо сбросить кеш запроса и получить обновленные данные. Кроме того, нужно сбросить кеш запроса списка постов.
В прошлый раз мы использовали теги для инвалидации кеша. Можно попробовать добавить тег 'Post' к запросу
getPost
и сбрасывать его в мутации editPost
. Но это приведет к сбросу всех ранее запрошенных постов, даже если они не редактировались.Необходимо "уточнить" тег, добавить в него параметры, чтобы он указывал на конкретную сущность. Вместо строки 'Post' мы можем указать объект
{type: 'Post', id: 123 }
.Поле
providesTags
может принимать функцию. После выполнения запроса эта функция вызывается, а в качестве параметров ей передаются результаты запроса. На их основе можно сформировать массив тегов:getPosts: builder.query({Таким образом, каждый пост (и отдельный, и в списке) теперь помечен собственным тегом.
// ...
providesTags: function (result = [], error, arg) {
return [
'Post',
...result.map(function(id) { return { type: 'Post', id }; })
]
}
}),
getPost: builder.query({
// ...
providesTags: function(result, error, arg) {
return [
{ type: 'Post', id: arg }
]
}
})
Поле
invalidatesTags
также может принимать функцию. После выполнения запроса она получит его данные и сможет точно определить, какие статьи нужно сбросить:editPost: builder.mutation({Важно: для эндпоинта
// ...
invalidatesTags: function(result, error, arg) {
return [
{ type: 'Post', id: arg.id }
]
}
})
getPosts
в список тегов включен простой тег 'Post' без уточнения. Это нужно, чтобы список сбрасывался целиком при добавлении новой статьи. Но это также сбросит все отдельные статьи. Имеет смысл уточнить и этот тег, который относится только к списку: { type: 'Post', id: 'LIST' }#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
CodeSandbox
Redux Essentials. RTK Query 2. React Junior - CodeSandbox
Redux Essentials. RTK Query 2. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
Redux Essentials 20. RTK Query. Ручная работа с эндпоинтами
Продолжаем переписывать всю API-часть приложения с помощью RTK Query. На очереди пользователи.
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-3-react-junior-mxklq3?file=/src/features/users/usersSlice.js
Создаем новый query-эндпоинт
Ручной вызов эндпоинта
Сейчас список пользователей запрашивается в файле
Посмотрим на
Таким образом, есть возможность выполнить запрос "вручную", не прибегая к хукам.
Теперь нужно сделать так, чтобы компоненты получали данные из
Документация предлагает временно отказаться от адаптера. Пока просто заменим существующие селекторы на новые, которые получают данные из
Создадим и экспортируем также селекторы
Кроме того, удаляем
#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
Продолжаем переписывать всю API-часть приложения с помощью RTK Query. На очереди пользователи.
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-3-react-junior-mxklq3?file=/src/features/users/usersSlice.js
Создаем новый query-эндпоинт
getUsers
.Ручной вызов эндпоинта
Сейчас список пользователей запрашивается в файле
index.js
, вне компонентов приложения, так как он нужен постоянно. RTK Query тоже позволяет так делать.Посмотрим на
apiSlice
в консоли. У него много разных свойств, некоторыми из которых мы уже пользовались (apiSlice.reducer
и apiSlice.middlware
). Помимо прочего там есть поле endpoints
, и у каждого эндпоинта есть метод initiate
. Это функция-триггер, которая запускает выполнение запроса. Таким образом, есть возможность выполнить запрос "вручную", не прибегая к хукам.
store.dispatch(apiSlice.endpoints.getUsers.initiate())При этом создается подписка на результат запроса, который кешируется. Если необходимость в этих данных отпадет, нужно будет отписаться самостоятельно:
// подпискаСоздание селектора
const result = dispatch(api.endpoints.getPosts.initiate())
// отписка
result.unsubscribe()
Теперь нужно сделать так, чтобы компоненты получали данные из
apiSlice
. Сейчас селекторы создаются в usersSlice
, причем там мы используем entityAdapter, чтобы управлять коллекцией пользователей.Документация предлагает временно отказаться от адаптера. Пока просто заменим существующие селекторы на новые, которые получают данные из
apiSlice
. Для получения данных нужен метод эндпоинта select
.export const selectUsersResult = apiSlice.endpoints.getUsers.select()Функция
select
создает мемоизированный селектор. В качестве аргумента она может принимать cache key, который должен совпадать с ключом, переданным в функцию initiate
(при ручном вызове) или в хук эндпоинта. Разберемся в этом позже, нам нужен весь список пользователей, так что пока можно обойтись без ключа.Создадим и экспортируем также селекторы
getUsers
и getUserById
, которые уже существуют, чтобы компоненты могли продолжать ими пользоваться.Кроме того, удаляем
usersReducer
из configureStore
.#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
👍2
Redux Essentials 21. RTK Query. Разделение API-слайса
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-4-react-junior-1h2or8?file=/src/features/users/usersSlice.js
RTK Query предоставляет метод
1. Вызываем метод
2. Метод вернет обновленный объект
3. Далее мы можем использовать
4. Удаляем
5. Отдельно экспортируем эндпоинт:
#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-4-react-junior-1h2or8?file=/src/features/users/usersSlice.js
apiSlice
уже сильно разросся, пора его разделить. RTK Query предоставляет метод
injectEndpoints
. С его помощью мы можем вынести всю работу с пользователями в отдельный файл - в usersSlice
.1. Вызываем метод
api.injectEndpoints
и передаем ему набор эндпоинтов.2. Метод вернет обновленный объект
extendedApiSlice
- это тот же самый apiSlice
, эндпоинты добавлены через мутацию.3. Далее мы можем использовать
extendedApiSlice
вместо apiSlice
для ясности.4. Удаляем
getUsers
из apiSlice
.5. Отдельно экспортируем эндпоинт:
extendedApiSlice.endpoints.getUsers
, чтобы было удобнее инициировать его в файле index.js.#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
👍1
Redux Essentials 22. RTK Query + EntityAdapter
Возвращаемся к EntityAdapter в userSlice. Все оказалось очень просто: при получении данных запроса в
https://codesandbox.io/s/redux-essentials-rtk-query-5-react-junior-b5ebze?file=/src/features/users/usersSlice.js
Возвращаемся к EntityAdapter в userSlice. Все оказалось очень просто: при получении данных запроса в
transformResponse
просто вызываем метод usersAdapter.setAll
, чтобы сохранить в нужном виде. https://codesandbox.io/s/redux-essentials-rtk-query-5-react-junior-b5ebze?file=/src/features/users/usersSlice.js
const usersAdapter = createEntityAdapter();Все селекторы можно вернуть, как было, но потребуется внести несколько изменений в логику извлечения данных из хранилища.
const initialState = usersAdapter.getInitialState();
getUsers: builder.query({
// ...
transformResponse: function (responseData) {
return usersAdapter.setAll(initialState, responseData);
}
})
// получение данных запроса из apiSlice#redux #управлениесостоянием #обменданными #rtkquery #документация #примерыкода
export const selectUsersResult = getUsersEndpoint.select();
// извлечение данных из запроса, если он выполнен
// результат работы entity adapter ({ids, entities}) или undefined
const selectUsersData = createSelector(
selectUsersResult,
function (usersResult) {
return usersResult.data;
}
);
export const {
selectAll: getUsers,
selectById: getUserById
} = usersAdapter.getSelectors(
function(state) {
return selectUsersData(state) ?? initialState;
}
);
CodeSandbox
Redux Essentials. RTK Query 5. React Junior - CodeSandbox
Redux Essentials. RTK Query 5. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍2
RTK Query. Query hook: параметры
В хук запроса, сгенерированный для эндпоинта, можно передать параметры:
-
-
Настройки есть следующие:
-
-
-
-
-
-
#обменданными #rtkquery #документация
В хук запроса, сгенерированный для эндпоинта, можно передать параметры:
-
queryArg
(параметр для генерации урла запроса, передается в функцию query
) -
queryOptions
(объект с настройками). Настройки есть следующие:
-
skip
- пропустить выполнение запроса для текущего рендера.-
pollingInterval
- для автоматического перезапроса данных.-
selectFromResult
- позволяет изменить возвращаемое хуком значение (оптимизировано для рендера).-
refetchOnMountOrArgChange
-
refetchOnFocus
- refetch при возвращении фокуса на вкладку браузера.-
refetchOnReconnect
- refetch при восстановлении сетевого соединения, если оно было потеряно.#обменданными #rtkquery #документация
👍1
Redux Essentials 23. Выбор данных из запроса
Теперь займемся страницей пользователя, на которой выводятся отфильтрованные по автору посты.
https://codesandbox.io/s/redux-essentials-rtk-query-6-react-junior-kfzw2t?file=/src/features/users/UserPage.js
Воспользуемся хуком
При любом изменении
#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
Теперь займемся страницей пользователя, на которой выводятся отфильтрованные по автору посты.
https://codesandbox.io/s/redux-essentials-rtk-query-6-react-junior-kfzw2t?file=/src/features/users/UserPage.js
Воспользуемся хуком
useGetPostsQuery
, чтобы получить полный список постов и настройкой selectFromResult
(параметры хука запроса), чтобы отфильтровать статьи по автору.const { postsForUser } = useGetPostsQuery(undefined, {
selectFromResult: function(result) {
return {
...result,
postsForUser: (result.data || []).filter(function(post) {
return post.user === userId
})
}
}
});
При любом изменении
state
массив postsForUser
будет пересоздаваться, вызывая перерендер компонента, поэтому нужно обернуть извлечение данных в мемоизированный селектор.#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
👍1
Трансформация данных запроса: 3 подхода
Мы получаем данные из API в одном виде, но для использования может потребоваться их изменение. Сделать это можно в трех местах:
1. Сразу после получения. Преобразуем ответ с помощью
2. В компоненте. Получаем данные, сохраненные в кеше, и извлекаем из них то, что нужно. Рекомендуется использовать
3. В хуке запроса. Отбираем нужные данные с помощью опции
#redux #rtkquery #обменданными #паттерны
Мы получаем данные из API в одном виде, но для использования может потребоваться их изменение. Сделать это можно в трех местах:
1. Сразу после получения. Преобразуем ответ с помощью
transformResponse
и сохраняем в кеше уже измененные данные. Имеет смысл, если новый формат подходит всем потребителям. Можно сочетать с entity adapter.2. В компоненте. Получаем данные, сохраненные в кеше, и извлекаем из них то, что нужно. Рекомендуется использовать
useMemo
для избежания ненужных перерендерингов. Полезно, если одному компоненту нужны данные в другом формате.3. В хуке запроса. Отбираем нужные данные с помощью опции
selectFromResult
. Полезно, если компоненту нужна только часть данных.#redux #rtkquery #обменданными #паттерны
👍2
Redux Essentials 24. RTK Query. Оптимистичные обновления
Переходим к реакциям на статьи.
https://codesandbox.io/s/redux-essentials-rtk-query-7-react-junior-uzedjr?file=/src/features/api/apiSlice.js
Добавляем эндпоинт-мутацию
После того, как пользователь поставил реакцию, нужно отправить запрос и обновить данные статьи, чтобы показать изменения.
Но ради такого мелкого изменения не хочется по новой запрашивать целый список. Для таких ситуаций можно воспользоваться техникой "оптимистичного обновления".
По умолчанию мы предполагаем, что обновление пройдет успешно, и хотим сразу показать пользователю изменение счетчика. Можно подправить уже сохраненные данные, а если запрос вдруг не выполнится, просто отменить эту правку.
Для эндпоинта можно указать метод
Таким образом, запрос отправляется, но мы не хотим ждать его результата, а хотим внести изменения немедленно. У
Теперь нужно только задиспатчить этот thunk, чтобы изменения отобразились в компоненте.
Если же запрос на сервер (
Осталось только внести изменения в компонент
#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
Переходим к реакциям на статьи.
https://codesandbox.io/s/redux-essentials-rtk-query-7-react-junior-uzedjr?file=/src/features/api/apiSlice.js
Добавляем эндпоинт-мутацию
addReaction
.После того, как пользователь поставил реакцию, нужно отправить запрос и обновить данные статьи, чтобы показать изменения.
addReaction: builder.mutation({
query: function({ postId, reaction }) {},
invalidatesTags: function(result, error, arg) {
return [
{ type: 'Post', id: arg.postId }
];
}
})
Но ради такого мелкого изменения не хочется по новой запрашивать целый список. Для таких ситуаций можно воспользоваться техникой "оптимистичного обновления".
По умолчанию мы предполагаем, что обновление пройдет успешно, и хотим сразу показать пользователю изменение счетчика. Можно подправить уже сохраненные данные, а если запрос вдруг не выполнится, просто отменить эту правку.
Для эндпоинта можно указать метод
onQueryStarted
. Это функция, которая при вызове получит два параметра - arg
и thunkApi
, в котором нас интересуют два метода - dispatch
для отправки экшена и queryFulfilled
- промис отправленного запроса.Таким образом, запрос отправляется, но мы не хотим ждать его результата, а хотим внести изменения немедленно. У
apiSlice
есть свойство utils
, а в нем метод updateQueryData
. Он позволяет изменить ранее сохраненные данные. Для этого нужно указать название эндпоинта, ключ кеширования (если нужно) и собственно функцию для обновления.const patchThunk = apiSlice.util.updateQueryData('getPosts', undefined, function(draft) {
// ... вносим изменения в данные draft
// данные можно мутировать
});
Теперь нужно только задиспатчить этот thunk, чтобы изменения отобразились в компоненте.
const patchResult = thunkApi.dispatch(patchThunk);
Если же запрос на сервер (
queryFulfilled
) не выполнится, патч можно отменить, вызвав метод patchResult.undo()
.Осталось только внести изменения в компонент
ReactionButton
, чтобы он использовал хук новой мутации.#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
👍1
Redux Essentials 25. RTK Query. Потоковое обновление кеша
И наконец, осталось только переделать уведомления.
В реально приложении этот функционал скорее всего будет реализован с помощью сокетов. Получаем исходный список уведомлений, а дальше подписываемся на сокет-канал и ждем новых сообщений.
https://codesandbox.io/s/redux-essentials-rtk-query-7-react-junior-uzedjr?file=/src/features/notifications/notificationsSlice.js
Для демонстрационных целей напишем фейковый сокет-сервер, который будет через некоторый интервал генерировать новые уведомления.
Создание эндпоинта
Создадим новый эндпоинт
Экспортируем хук
Подписка на новые уведомления
У эндпоинта есть метод жизненного цикла
Внутри этого метода мы можем подписаться на сокет-канал.
Метод принимает два параметра:
Последовательность действий:
- ждем, пока выполнится основной запрос (
- подписываемся на сокет-канал, при получении новых уведомлений добавляем их к кешированным ранее данным (
- отслеживаем удаление кеша (
Непрочитанные уведомления
Теперь список уведомлений хранится в
При добавлении новых уведомлений в кеш, нужно добавлять их и в
В
Осталось только в компоненте
#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
И наконец, осталось только переделать уведомления.
В реально приложении этот функционал скорее всего будет реализован с помощью сокетов. Получаем исходный список уведомлений, а дальше подписываемся на сокет-канал и ждем новых сообщений.
https://codesandbox.io/s/redux-essentials-rtk-query-7-react-junior-uzedjr?file=/src/features/notifications/notificationsSlice.js
Для демонстрационных целей напишем фейковый сокет-сервер, который будет через некоторый интервал генерировать новые уведомления.
Создание эндпоинта
Создадим новый эндпоинт
getNotifications
, который будет получать исходный список. Для удобства вынесем его в файл notificationsSlice.js
и подключим с помощью метода apiSlice.injectEndpoints
.Экспортируем хук
useGetNotificatinsQuery
и используем его в компоненте NotificationsList
. Тут ничего нового.Подписка на новые уведомления
У эндпоинта есть метод жизненного цикла
onCacheEntryAdded
. Он вызывается в тот момент, когда эндпоинт добавляется в кеш, то есть для него "бронируется" там место (данные при этом еще не получены).Внутри этого метода мы можем подписаться на сокет-канал.
Метод принимает два параметра:
arg
и thunkApi
. В последнем есть несколько полезных методов и данных:const {
updateCachedData,
cacheDataLoaded,
cacheEntryRemoved,
dispatch
} = thunkApi;
Последовательность действий:
- ждем, пока выполнится основной запрос (
cacheDataLoaded
)- подписываемся на сокет-канал, при получении новых уведомлений добавляем их к кешированным ранее данным (
updateCachedData
)- отслеживаем удаление кеша (
cacheEntryRemoved
), закрываем каналНепрочитанные уведомления
Теперь список уведомлений хранится в
apiSlice
. Но нам еще нужно хранить их состояние (непрочитанные/прочитанные). Используем для этого уже существующий notificationsSlice
, только вместо самих уведомлений поместим туда данные об их состоянии.При добавлении новых уведомлений в кеш, нужно добавлять их и в
notificationsSlice
. Добавление происходит при выполнении базового запроса (экшен extendedApi.endpoints.getNotifications.matchFulfilled
), а также при получении новых данных через сокет. Для второго случая создадим отдельный экшен notificationsReceived
(используем утилитарную функцию createAction
).В
extraReducers
отслеживаем нужные экшены (builder.addMatcher
) и добавляем новые элементы в список.Осталось только в компоненте
NotificationsList
получить состояние уведомлений и отметить их как нужно.#redux #управлениесостоянием #rtkquery #обменданными #документация #примерыкода
CodeSandbox
Redux Essentials. RTK Query 7. React Junior - CodeSandbox
Redux Essentials. RTK Query 7. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
RTK Query. Резюме
Небольшое подведение итогов по RTK Query после прохождения руководства.
RTK Query работает поверх Redux Toolkit, используя его основные концепции.
Предполагается, что вся работа с API в проекте будет собрана в отдельный слайс, созданный с помощью функции
Эндпоинт может быть запросом (query) или мутацией (mutation).
У каждого эндпоинта есть поле
При необходимости, часть эндпоинтов можно перенести в отдельный файл и подключить к слайсу через
Все полученные данные хранятся в кеше. Если на эндпоинт нет подписок, его кеш через некоторое время сбрасывается.
Каждый эндпоинт можно пометить тегом (строка или объект), который можно инвалидировать (принудительно сбросить кеш и вызвать перезапуск запроса) в другом эндпоинте (уточненные теги).
Для эндпоинта генерируется хук (хуки запросов https://t.me/react_junior/342), который можно использовать в компонентах. Результат работы хука помимо данных содержит информацию о статусе запроса (`isFetching`,
Можно работать с эндпоинтами и без хуков, они предоставляют ряд методов (`initiate()`, `select()`) (ручная работа с эндпоинтами).
RTK Query поддерживает оптимистичные обновления кеша, для этого используем метод жизненного цикла
Кроме того, возможно обновление кеша "по необходимости", например, при подписке на сокет-канал (потоковое обновление кеша). Для этого используем метод жизненного цикла
#redux #rtkquery #обменданными
Небольшое подведение итогов по RTK Query после прохождения руководства.
RTK Query работает поверх Redux Toolkit, используя его основные концепции.
Предполагается, что вся работа с API в проекте будет собрана в отдельный слайс, созданный с помощью функции
createApi
. Тут можно настроить, как именно должен выполняться запрос (`baseQuery`), а также указать набор эндпоинтов (`endpoints`).Эндпоинт может быть запросом (query) или мутацией (mutation).
У каждого эндпоинта есть поле
query
, формирующее урл запроса. Полученный ответ можно обработать в методе transformResponse
. Кроме того, можно форматировать данные прямо в компоненте (три подхода к форматированию данных)При необходимости, часть эндпоинтов можно перенести в отдельный файл и подключить к слайсу через
apiSlice.injectEndpoints
(разделение эндпоинтов).Все полученные данные хранятся в кеше. Если на эндпоинт нет подписок, его кеш через некоторое время сбрасывается.
Каждый эндпоинт можно пометить тегом (строка или объект), который можно инвалидировать (принудительно сбросить кеш и вызвать перезапуск запроса) в другом эндпоинте (уточненные теги).
Для эндпоинта генерируется хук (хуки запросов https://t.me/react_junior/342), который можно использовать в компонентах. Результат работы хука помимо данных содержит информацию о статусе запроса (`isFetching`,
isLoading
, `isError`). Кроме того, хук может принимать параметры для автоматического перезапроса данных и для выборки нужных данных из кеша (`selectFromResult`) (параметры хука запроса).Можно работать с эндпоинтами и без хуков, они предоставляют ряд методов (`initiate()`, `select()`) (ручная работа с эндпоинтами).
RTK Query поддерживает оптимистичные обновления кеша, для этого используем метод жизненного цикла
onQueryStarted
и метод обновления apiSlice.util.updateQueryData
.Кроме того, возможно обновление кеша "по необходимости", например, при подписке на сокет-канал (потоковое обновление кеша). Для этого используем метод жизненного цикла
onCacheEntryAdded
.#redux #rtkquery #обменданными
Telegram
React Junior
Redux Essentials 16. RTK Query. Выполнение запросов
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
baseQuery
Основная (обязательная) настройка в методе createApi - это baseQuery. Это функция…
Проект: https://codesandbox.io/s/redux-essentials-rtk-query-react-junior-lced2j?file=/src/features/api/apiSlice.js
baseQuery
Основная (обязательная) настройка в методе createApi - это baseQuery. Это функция…
👍4
RTK Query
Освежаю знания об RTK Query
RTK Query - это часть Redux Toolkit, которая предназначена для удобной работы с API. Она собирает все, что относится к API в одном месте и дает нам много приятного синтаксического сахара.
Заводим для API отдельный слайс, где будут лежать все данные, полученные с сервера. Но не обычный слайс, который
Подключить этот api-слайс к стору посложнее, чем обычный, тут нужно и редьюсер добавить, и специальный миддлвар.
В api-слайсе определяем функцию, которая будет осуществлять запросы -
На этом техническая подготовка заканчивается и начинается собственно логика обмена данными - поле
Примечание: можно выполнить запрос и «вручную» без использования хука.
Отправка данных на сервер работает практически так же, как и вытягивание, только эндпоинт нужно немного по-другому оформить (через `builder.mutation`). Хук тоже немного другой.
Самое приятное, что запросы к серверу кешируются, однако кеш иногда приходится сбрасывать. Это можно сделать напрямую руками, с помощью метода
Конечно, api-слайс можно расчленять (injectEndpoints).
RTK Query предлагает продвинутые техники работы с API, например, оптимистичное обновление, когда данные меняются сразу, а запрос выполняется уже в фоне. Еще есть возможность подписаться на источник событий (сокет-канал) , чтобы получать данные из него.
Предыдущее резюме по RTK Query, с большим количество технических подробностей.
#управлениесостоянием #rtkquery #обменданными
Освежаю знания об RTK Query
RTK Query - это часть Redux Toolkit, которая предназначена для удобной работы с API. Она собирает все, что относится к API в одном месте и дает нам много приятного синтаксического сахара.
Заводим для API отдельный слайс, где будут лежать все данные, полученные с сервера. Но не обычный слайс, который
createSlice
, а прокачанный слайс, который createApi
.Подключить этот api-слайс к стору посложнее, чем обычный, тут нужно и редьюсер добавить, и специальный миддлвар.
В api-слайсе определяем функцию, которая будет осуществлять запросы -
baseQuery
.На этом техническая подготовка заканчивается и начинается собственно логика обмена данными - поле
endpoints
. Тут мы получаем builder
и с его помощью (`builder.query`) создаем массив наших эндпоинтов (есть много разных настроек) . Каждый эндпоинт на выходе из слайса создает себе личный хук , который можно дернуть в любом месте приложения. А в этом хуке уже предусмотрена куча удобных поле - data
, isLoading
, error
и т.п. И дополнительно можно закинуть ряд настроек, вроде селектора . То есть вытаскивать данные из API со всеми удобствами мы уже можем. Можно даже сочетать все это дело с EnitityAdapter. Примечание: можно выполнить запрос и «вручную» без использования хука.
Отправка данных на сервер работает практически так же, как и вытягивание, только эндпоинт нужно немного по-другому оформить (через `builder.mutation`). Хук тоже немного другой.
Самое приятное, что запросы к серверу кешируются, однако кеш иногда приходится сбрасывать. Это можно сделать напрямую руками, с помощью метода
refetch
, который есть в хуках. Но лучше настроить зависимости с помощью системы тегов, чтобы RTK Query сбрасывала то, что нужно, самостоятельно. Конечно, api-слайс можно расчленять (injectEndpoints).
RTK Query предлагает продвинутые техники работы с API, например, оптимистичное обновление, когда данные меняются сразу, а запрос выполняется уже в фоне. Еще есть возможность подписаться на источник событий (сокет-канал) , чтобы получать данные из него.
Предыдущее резюме по RTK Query, с большим количество технических подробностей.
#управлениесостоянием #rtkquery #обменданными
Telegram
React Junior
Redux Essentials 16. RTK Query. Создание слайса
RTK Query - это еще один уровень абстракции над абстракциями Redux, позволяющий инкапсулировать работу с API: методы получения/обновления/удаления данных, состояние выполнения запроса, синхронизация состояния…
RTK Query - это еще один уровень абстракции над абстракциями Redux, позволяющий инкапсулировать работу с API: методы получения/обновления/удаления данных, состояние выполнения запроса, синхронизация состояния…
🔥3👍2