# Вывод результатов работы thunk в компоненте в Redux

На прошлом занятии мы отправили POST-запрос с помощью thunk `addProduct`. Давайте теперь отобразим результаты его работы в компоненте.

Откроем наше приложение с продуктами, а в нем файл `NewProductForm.jsx`, поскольку этот компонент ответственен за добавление нового продукта. Посмотрим на строчки с импортом. Заменим импорт экшена `productAdded`, на импорт thunk `addProduct`:

`import { addProduct } from './productsSlice'`

Теперь, поскольку мы не отслеживаем в слайсе статус `'pending'` запроса, давайте сделаем так, чтобы пользователь смог нажать на кнопку с сохранением продукта только один раз, ведь нам не нужны те же самые повторные запросы. Для этого заведем еще один локальный стейт:

`const [requestStatus, setRequestStatus] = useState('idle')`

Далее после обработчиков и перед функцией `onSaveProductClick` напишем код, в котором проверим, все ли поля формы у нас заполнены и находится ли статус запроса в `'idle'`:

`const canBeSaved = [name, desc, price, amount, sellerId].every(Boolean) && requestStatus === 'idle'`

Затем мы изменим код для `onSaveProductClick`. Во-первых это будет асинхронная функция и она будет выполняться, если верно вышеприведенное условие:

`const onSaveProductClick = async () => { if (canBeSaved) {} }`

Несмотря на то, что мы в слайсе не отслеживаем статус `'rejected'`, мы все равно можем вывести в консоль ошибку, для этого воспользуемся конструкцией `try-catch`. Также здесь мы добавим еще и `finally`, чтобы после выполнения запроса снова установить локальный стейт в `'idle'`:

`const onSaveProductClick = async () => { if (canBeSaved) { try { } catch (err) { console.error(save product error: , err) } finally { setRequestStatus('idle') } } }`

С `catch` и `finally` блоками мы разобрались, давайте напишем код для блока `try`. Здесь мы установим локальный статус в `'in pogress'`, пока нам не вернется какой-нибудь ответ в результате работы thunk, затем отправим наш thunk `addProduct`. Использовать конструкцию `try-catch` в зависимости от типа ответа нам поможет функция RTK `unwrap`, которую он добавляет к возвращаемому промису. Затем, если запрос был успешен мы устанавливаем локальные стейты в их начальные состояния. Полный код для `onSaveProductClick` будет выглядеть так:

`const onSaveProductClick = async () => { if (canBeSaved) { try { setRequestStatus('in progress') await dispatch( addProduct({ name, desc, price, amount, seller: sellerId })).unwrap() setName('') setDesc('') setPrice(0) setAmount(0) setSellerId('') } catch (err) { console.error('save product error: ', err) } finally { setRequestStatus('idle') } } }`

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

Откройте ваше приложение со студентами. Откройте в нем файл `NewStudentForm.jsx`. Добавьте еще один локальный стейт `requestStatus`, и установите его изначально в `'idle'`. Ознакомившись с материалами урока, заведите переменную `canBeSaved`, с помощью которой кнопка сохранения новых данных студента будет работать/не работать, в зависимости от значения `requestStatus` и от заполненности полей.

Напишите асинхронный код для `onSaveStudentClick`, который будет менять значение `requestStatus` по ситуации, отправлять thunk `addProduct` с данными нового студента, очищать поля в случае успешного запроса и выводить в консоль ошибку в случае неудачи, как показано в уроке. Используйте для этого конструкцию `try-catch` и функцию RTK `unwrap`.

Запустите ваше приложение, добавьте нового студента и убедитесь, что все работает.

← →
↑