# Дополнительные редьюсеры в Redux

Давайте откроем наше приложение с продуктами, а в нем файл `productsSlice.js`. Наверное вы заметили, что мы создавали thunk `fetchProducts` как отдельную функцию? Мы сделали так, потому что `createSlice` не поддерживает определение thunks. Как же нам в этом случае заставить reducer слайса `products` отвечать на экшены, которые определены за пределами `products`? Ведь нам как раз нужно обработать экшены, которые посылает thunk `fetchProducts`.

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

Давайте теперь в теле функции `createSlice` после свойства `reducers` со всеми редьюсерами добавим еще один метод `extraReducers`:

`extraReducers() {},`

Этому методу мы должны передать объект `builder`, у которого есть методы, с помощью которых можно добавить дополнительные редьюсеры:

`extraReducers(builder) {},`

Мы будем использовать один из методов `builder` - `addCase`, который первым параметром принимает action creator, а вторым reducer. Один из экшенов, который нам будет отправлять `fetchProducts` при запросе это `fetchProducts.pending`, что говорит нам о том, что запрос отправлен. Давайте в этом случае будем менять статус на `'in progress'` (до этого он был `'idle'`):

`extraReducers(builder) { builder.addCase(fetchProducts.pending, (state) => { state.status = 'in progress' }) },`

Теперь обработаем экшен, который отправится в случае успешного запроса. Здесь мы будем менять не только статус в стейте на `'success'`, но и заберем продукты в слайс `products` из `payload` экшена. Чтобы собрать все продукты нам понадобиться метод `concat`:

`extraReducers(builder) { builder .addCase(fetchProducts.pending, (state) => { state.status = 'in progress' }) .addCase(fetchProducts.fulfilled, (state, action) => { state.status = 'success' state.products = state.products.concat(action.payload) }) },`

В случае неудачного запроса мы поменяем статус на `'fail'` и запишем в стейт сообщение об ошибке:

`.addCase(fetchProducts.rejected, (state, action) => { state.status = 'fail' state.error = action.error.message })`

Если мы сейчас запустим наше приложение и в меню кликнем по `'Products'`, то через пару секунд (помните про задержку, которую мы выставили на сервере?) увидим список с продуктами.

Точно также мы увидим изменения и в Redux DevTools. Теперь наши продукты появятся и в стейте (посмотрите вкладку `'State'`), если вы кликнули по экшену `products/fetchProducts/fulfilled`. Там же появится и новый статус `'success'`. Кликните теперь на экшен `products/fetchProducts/pending` и посмотрите, чем теперь отличается вкладка `'State'`.

Единственный неприятный момент, который у вас может случиться (я говорил про это на предыдущем уроке) - это дублирование запроса данных. В результате чего, у нас в списке получится не `8`, а целых `16` продуктов и критические предупреждения в консоли разработчика. Давайте разберемся с этим на следующем уроке.

Откройте ваше приложение со студентами. Откройте в нем файл `studentsSlice.js`. В теле функции `createSlice` после свойства `reducers` добавьте свойство `extraReducers`. Передайте методу `extraReducers` `builder`.

С помощью метода `builder.addCase` добавьте обработку для экшенов `pending`, `fulfilled` и `rejected`, которые отправляет `fetchStudents` при запросе данных, как показано в уроке.

← →
↑