Дадатковыя рэдʼюсеры ў 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'
і запiшам у стэйт
паведамленне пра памылку:
.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
прадуктаў і крытычныя папярэджанні
у кансолі распрацоўніка. Давайце
разбярэмся з гэтым на наступным уроке.
Адчынiце ваша прыкладанне са студэнтамі.
Адчынiце ў ім файл studentsSlice.js
. У
целе функцыі createSlice
пасля ўласцівасці
reducers
дадайце ўласцівасць extraReducers
.
Перадайце метаду extraReducers
builder
.
З дапамогай метаду builder.addCase
дадайце апрацоўку для экшэнаў pending,
fulfilled і rejected, якія
адпраўляе fetchStudents
пры запыце
даных, як паказана ў уроку.