Вывод результатов работы 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.

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



Чат с GPT Компилятор