Вынікі працы 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.
Запусціце ваша прыкладанне, дадайце новага студэнта і пераканайцеся, што ўсё працуе.