Допълнителни редьосери в 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 при заявка
за данни, както е показано в урока.