Мы уже исследовали Redux в статье "Redux проще, чем вы думаете!" и узнали, что его нужно использовать, но все же есть некоторые проблемы, когда дело доходит до использования redux. Вот эти проблемы: 1. Конфигурация редукции слишком сложна 2. Редукс требует слишком много стандартного кода 3. Сам по себе он не делает ничего полезного, и нам нужно устанавливать такие пакеты, как redux-thunk, redux-saga, redux-persist и т. д. …

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

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

Я написал эту статью, предполагая, что вы ничего не знаете о редукции, но тем временем я сделал несколько «примечаний по редуксу» для людей, которые знакомы с редуксом или уже читали статью о редуксе. Так что, если вы не из тех, кто уже знает о редуксе, вам лучше не читать «редукционные заметки», если не хотите запутаться.

1. установите пакеты, которые вам нужны

npm установить @reduxjs/toolkit

@reduxjs/toolkit — это комплексный пакет, который включает в себя все, что нам нужно, и нам не нужно устанавливать redux-thunk или любые другие пакеты redux, кроме react-redux. мы используем избыточность для создания хранилища, а react-redux — это просто способ взаимодействия реакции с избыточностью, например: обновление глобального состояния, чтение глобального состояния…

2. Создайте папку **features** в папке src вашего проекта.

После создания папки функций мы создаем папку для каждого из наших действий, на изображении выше, которое является содержимым папки функций, мы создали папку с именем allProduct, которая связана с действиями продуктов, и папку с именем корзина, которая связана к таким действиям, как добавление или удаление товара из корзины или даже добавление товаров в корзину…

Каждая папка содержит два файла: 1. action.js 2. xxxSlice.js (вместо xxx можно поставить что угодно, но в нашем примере это cartSlice, потому что он находится в папке корзины).

› Примечание Redux: представьте файл среза в качестве редуктора, точно так же, как файл редуктора, который мы использовали для его имени xxxReducer, мы назовем файл слайса как xxxSlice, и мы не собираемся больше создавать файлы редуктора.

action.js содержит все необходимые нам действия, такие как добавление товаров в корзину, удаление товаров из корзины и т. д.:

CreateAsyncThunk — это функция из набора инструментов redux, которая принимает строку типа действия Redux и функцию обратного вызова для получения необходимых данных и их возврата. если нашим запросам нужно что-то вроде идентификатора или данных… мы просто передаем их как параметры нашей асинхронной функции обратного вызова. как вы можете видеть на изображении выше, когда нам нужен один параметр, мы можем просто передать его нашему обратному вызову (например, действие deleteFromCart), но если нам нужно более одного параметра, мы должны передать их как объект (например, updateCart, addToCart), потому что второй аргумент нашего асинхронного обратного вызова не для параметров.

после извлечения данных с помощью Axios или fetch или чего-либо еще) мы возвращаем данные, и этот асинхронный обратный вызов собирается отправить объект со свойством, названным полезной нагрузкой, и значением этой полезной нагрузки являются данные, которые мы получили от сервера.

› Примечание Redux: вы могли заметить, что с методом createAsyncThunk нам больше не нужно отправлять объект с типом и полезной нагрузкой, и, передавая уникальную строку в качестве первого аргумента этой функции, мы фактически отправляем тип и асинхронный обратный вызов будет сам обрабатывать полезную нагрузку.

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

Итак, создаем cartSlice для вышеуказанных действий:

createSlice исходит из redux-toolkit и представляет собой функцию, которая принимает объект опций:
опция name для именования слайса,
опция initialSatate для определения начального состояния,
опция extraReducer для определения различных case для наших действий и обновлений состояния, extraReducer — это функция, которая получает построитель, и внутри этой функции нам нужно определить наши случаи, как указано выше, метод addCase построителя принимает два параметра: 1. действие (импортированное из action.js) с статус действия, такой как выполнено, отклонено и ожидается, 2. обратный вызов, который обновляет состояние, и этот обратный вызов принимает два параметра: сначала начальное состояние, которое мы уже объявили, и действие, которое имеет свойство полезной нагрузки, равное тому, что возвращает действие .

Примечание: вы могли заметить, что имя, которое мы дали createSlice, — это имя, которое мы поместили в первую часть строки типа в первом параметре createAsyncThunk, таким образом, мы на самом деле говорим, что фрагмент с именем «cart ' просмотрит это действие типа "cart/addToCart" или "cart/deleteFromCart",…

› Примечание Redux: как и в редюсере, в котором у нас было InitialState, в createSlice у нас то же самое.

В приведенном выше примере, если действие getCart было отправлено и данные были успешно получены, первый случай, который мы добавим в extraReducers, будет вызван и обновит свойство value нашего состояния данными, полученными от действия.

Это еще один пример фрагмента с большим количеством случаев:

Как видите, у нас также есть статус «отклонено» и «ожидание», поэтому мы можем добавить кейс для этих статусов и сообщать избыточность всякий раз, когда действие было отправлено, но оно все еще находилось в статусе «ожидание» или «отклонено», вызывать этот кейс и обновлять ошибку или загрузку. свойство нашего состояния, поэтому мы можем использовать его на нашей странице, чтобы показать счетчик загрузки или предупреждение об ошибке,…

Примечание: в редуксе мы обычно объявляем определенное состояние для загрузки и устанавливаем его значение в true перед выполнением запроса и устанавливаем в false после запроса. но с redux-toolkit нам больше не нужно этого делать.

Важное примечание: объекты неизменяемы в javascript, поэтому нам не разрешено их изменять, и нам пришлось создать новый объект и скопировать в него свойства старого объекта и повторно инициализировать свойство, которое мы хотим обновить. вот так:
{…initialState,value: payload.action}
Этот способ может немного раздражать некоторых людей, поэтому нам не нужно делать это таким образом с помощью redux-toolkit и как вы можете видеть в приведенных выше примерах внутри кейсов, мы на самом деле так легко меняем свойство нашего объекта состояния. копирует в него старый и обновляет нужное свойство), поэтому нам больше не нужно иметь дело с этим надоедливым синтаксисом.

У нас есть еще один вариант для createSlice, который является редуктором: этот параметр используется для синхронных действий, и нам даже не нужно определять действия в отдельном файле, редукторы — это объект наших действий синхронизации, эти действия принимают два параметра, сначала начальное состояние а второй — это действие, которое является первым параметром, который мы дали нашему действию при его отправке:

После объявления действия внутри редукторов createSlice предоставляет нам объект действия, который содержит все действия, которые мы определили в параметре редукторов, и, как и в примере выше, мы можем деструктурировать его и экспортировать.

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

3. Создайте store.js в папке src

configureStore принимает объект с параметром под названием «редуктор», а параметр «редуктор» — это объект, содержащий все редьюсеры, которые мы экспортировали из наших слайсов, и всякий раз, когда мы отправляем действие, данные будут сохраняться здесь в конце.

› Примечание Redux: при использовании configureStore нам больше не нужно использовать combReducers или даже config reduxDevTool, потому что configureStore делает все это за нас.

4. Добавьте хранилище к провайдеру в src/index.js.

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

5. Использование действий и редукторов

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

  1. отправить действие для обновления данных:

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

2. Прочитайте обновленные данные внутри глобального состояния:

В приведенном выше примере мы используем хук useSelector, который исходит от react-redux и принимает обратный вызов, который имеет один параметр, который является нашим глобальным состоянием (опция редьюсера внутри объекта condifgureStore). всякий раз, когда мы отправляем действие, такое как addToCart или getCart или deleteFromCart, cartSlice будет следить за ним, и если случай, который мы добавляем внутри extraReducer, был доступен, он будет обновлять начальное состояние и передавать его свойству тележки внутри опции редьюсера метод конфигурасторе.

РТК-запрос

Если вы ищете другую структуру redux-toolkit, которая поможет вам с выборкой данных и кэшированием данных,… вы можете забыть обо всей вышеописанной структуре и использовать redux-toolkit так, как я вам сейчас расскажу:

1. Создайте папку services внутри папки src вашего проекта.

Эта папка содержит один файл с расширением xxxApi (вместо xxx можно указать что угодно, в нашем случае мы назовем его onlineShopApi.js)
Этот файл выглядит следующим образом:

createApi — это функция, которая принимает объект параметров:
reducerPath: reducerPath — это уникальный ключ, к которому ваша служба будет подключена в вашем магазине.

baseQuery: он может быть равен fetchBaseQUery, который представляет собой очень маленькую оболочку для fetch, предназначенную для упрощения запросов. он принимает объект, и мы можем добавить такие свойства, как baseUrl, чтобы упростить наши запросы.

конечные точки: это функция, которая получает параметр сборки и возвращает объект свойств, и каждое свойство равно builder.query или builder.mutation, который является функцией, которая получает объект:
Если конечная точка у нас есть для получения некоторых данных с помощью метода GET, нам нужно использовать builder.query, который получает объект, содержащий функцию с именем query, и возвращает строку нашей конечной точки.
Если у нас есть конечная точка для обновления некоторых данных с такими методами, как POST, DELETE, PATCH или PUT, нам нужно использовать builder.mutation, который получает функцию с именем query и возвращает объект с url (строка конечной точки), метод (PUT,…) и свойство body (если нам нужно это).

Любые данные или идентификатор или что-то еще, что нам нужно для нашего запроса, мы можем получить его как параметр функции запроса и использовать его (например, запрос getProductDetails или мутацию addToCart в приведенном выше примере), и не забудьте, если это более одного параметра вам нужно передать его как объект (например, мутацию addToCart).

Теперь createApi предоставляет нам обработчик для каждого запроса или мутации, объявленной нами внутри конечных точек, и мы можем деструктурировать эти обработчики и экспортировать их для использования в наших компонентах (точно так же, как последняя строка в приведенном выше примере).
эти обработчики названный createApi в следующем формате:
для конечных точек builder.query:
используйте + ваше имя + Query
например: useGetCartQuery , ловушки useGetProductDetailsQuery в приведенном выше примере.

для конечных точек builder.mutation:
используйте + ваше имя + Mutation
например: useDeleteFromCartMutation, useAddToCartMutation в приведенном выше примере.

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

2. Создайте файл хранилища в папке src вашего проекта.

Параметр configureStore немного отличается от того, что вы видели в предыдущей структуре:

Мы используем параметр reducerPath нашего API, чтобы назвать редуктор, который он возвращает в глобальном состоянии.

configureStore устанавливает некоторые промежуточные программы в наш магазин по умолчанию (например, промежуточные программы thunk, чтобы сделать избыточность способной использовать асинхронные действия), но когда мы используем структуру запроса rtk, мы также хотим добавить промежуточные программы, которые наш API возвращает в наш магазин. Итак, как и на изображении выше, мы объявляем параметр промежуточного программного обеспечения, который равен функции, которая принимает функцию с именем getDefaultMiddleware, и мы вызываем эту функцию, чтобы получить массив всех промежуточных программ по умолчанию, а также объединить промежуточное программное обеспечение, которое поступает из нашего API. к этому массиву.

› Узел Redux: каждое промежуточное ПО, которое мы поместили в массив промежуточного ПО в configreStore, будет использоваться с applyMiddleware, которое у нас было внутри Redux.

Примечание: промежуточное ПО, созданное нашим API, поможет нам в кэшировании, аннулировании и т. д. процессах.

3. Добавьте хранилище к провайдеру в src/index.js.

Этот шаг такой же, как и в предыдущей структуре.

4. Использование хуков запросов и мутаций

Мы либо хотим запросить данные и получить что-то с помощью хуков запроса, либо обновить данные, удалив, отредактировав или создав хуки мутации.

  1. Использование хуков запросов для получения данных:

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

2. Использование перехватчиков мутаций для обновления данных:

Как вы видите в приведенном выше примере, перехватчики мутаций дают нам кортеж. Первый элемент кортежа — это функция «триггер», а второй элемент содержит объект результатов с данными, isLoading, isError,… свойствами.

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

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

До свидания и удачи🤞