Дадатковыя рэдʼюсеры ў 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 пры запыце
даных, як паказана ў уроку.