АКЦЫЯ: бясплатныя месячныя курсы па стварэнні сайтаў
на выбар: вёрстка, JavaScript, PHP, Python або фрэймворкі. Сёння апошні дзень для запісу! Націскай!
⊗jsrxPmATER 48 of 57 menu

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

byenru