Вынікі працы thunk у кампаненце ў Redux

На мінулым заняцці мы адправілі POST-запыт з дапамогай thunk addProduct. Давайце цяпер адлюструем вынікі яго працы ў кампаненце.

Адкрыем наша прыкладанне з прадуктамі, а ў ім файл NewProductForm.jsx, паколькі гэты кампанент адказны за дадаванне новага прадукта. Паглядзім на радкі з імпартам. Замянім імпарт экшна productAdded, на імпарт thunk addProduct:

products/NewProductForm.jsximport { addProduct } from './productsSlice'

Цяпер, паколькі мы не адсочваем у слайсе статус 'pending' запыту, давайце зробім так, каб карыстальнік змог націснуць на кнопку з захаваннем прадукта толькі адзін раз, бо нам не патрэбныя тыя ж самыя паўторныя запыты. Для гэтага завядзем яшчэ адзін лакальны стэйт:

products/NewProductForm.jsxconst [requestStatus, setRequestStatus] = useState('idle')

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

products/NewProductForm.jsxconst canBeSaved =
  [name, desc, price, amount, sellerId].every(Boolean) &&
  requestStatus === 'idle'

Затым мы зменым код для onSaveProductClick. Па-першае гэта будзе асінхронная функцыя і яна будзе выконвацца, калі дакладна вышэйпрыведзеная ўмова:

products/NewProductForm.jsxconst onSaveProductClick = async () => {
  if (canBeSaved) {}
}

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

products/NewProductForm.jsxconst 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 будзе выглядаць так:

products/NewProductForm.jsxconst 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 і пабягайце па яго ўкладках, паглядзіце на экшны і як мяняецца ваш стэйт.

Задание 1

Адкрыйце ваша прыкладанне са студэнтамі. Адкрыйце ў ім файл NewStudentForm.jsx. Дадайце яшчэ адзін лакальны стэйт requestStatus, і ўсталюйце яго першапачаткова ў 'idle'. Азнаёміўшыся з матэрыяламі ўрока, завядзіце пераменную canBeSaved, з дапамогай якой кнопка захавання новых дадзеных студэнта будзе працаваць/не працаваць, у залежнасці ад значэння requestStatus і ад запоўненасці палёў.

Задание 2

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

Задание 3

Запусціце ваша прыкладанне, дадайце новага студэнта і пераканайцеся, што ўсё працуе.