React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
Список тегов для более удобного поиска постов

👉 Основные понятия

#компоненты
#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 предоставляет две основные функции:

- 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

Основная (обязательная) настройка в методе createApi - это baseQuery. Это функция, которая непосредственно выполняет запросы.

В качестве такой функции можно использовать встроенную fetchBaseQuery - обертку над стандартным методом fetch.

Внутри одного API-слайса предполагается, что все запросы осуществляются к одному серверу (это необязательно). Так что здесь можно установить базовые настройки запроса, например, baseUrl - фрагмент урла, с которого начинаются все эндпоинты.

const apiSlice = createApi({
// ...
baseQuery: fetchBaseQuery({ baseUrl: '/fakeApi' })
})

Но можно использовать и собственную функцию для выполнения запросов. Важно, чтобы она возвращала ответ в нужном формате. Полученные данные должны находиться в поле data, а ошибка, если она есть, в поле error.

Так как в моем проекте реального API нет, придется использовать кастомную функцию customFetchBaseQuery, которая вместо настоящих запросов просто обращается к модулю fakeApi.

Вместо этого можно, например, реализовать запросы с помощью библиотеки axios.

#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
👍2
Redux Essentials 16. RTK Query. Эндпоинты

Проект: 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({
// ...
endpoints: function(builder) {
return {
getPosts: builder.query({
query: function() { return "/posts" },
transformResponse: function(response) { return response.data }
})
}
}
})

#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
👍2
Redux Essentials 16. RTK Query. Использование данных

Проект: 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, чтобы сортировка происходила только при изменении массива posts.

#redux #rtkquery #обменданными #управлениесостоянием #документация #примерыкода
👍3
Redux Essentials 17. RTK Query. Страница статьи

Так как список постов мигрировал в 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

Создание нового поста

Добавляем новый эндпоинт 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 #документация #примерыкода
👍2