Падрыхтоўка даных для аб'екта action у Redux

Нядаўна мы гаварылі з вамі пра тое, што функцыя createSlice чакае адзін аргумент пры стварэнні action.payload. З аднаго боку гэта спрашчае яе выкарыстанне, з другога ж можа патрабаваць дадатковых дзеянняў для падрыхтоўкі змесціва аб'екта action.

Давайце адчынём наша прыкладанне з прадуктамі, а ў ім файл NewProductForm.jsx. Звярніце ўвагу на наступны радок кода:

NewProductForm.jsxdispatch(productAdded({
  id: nanoid(), name, desc, price, amount
}))

Тут мы збіраем payload аб'ект прама ў React кампаненце і перадаём яго ў экшэн productAdded. А што калі нам прыдзецца адпраўляць такі ж экшэн з некалькіх кампанентаў або логіка для зборкі акажацца складанай? Па ідэі нашаму кампаненту павінна быць усё роўна як выглядае аб'ект у payload для дадзенага action. Да таго ж нас не задавальняе сталае дубляванне кода.

Гэтыя праблемы нам зноў можа дапамагчы вырашыць наш знакаміты createSlice, прыколькі пры напісанні рэдьюсера ён дазваляе нам выкарыстоўваць callback-функцыю prepare, у якой можна пісаць розную логіку, генераваць выпадковыя лікі і іншае. У такім выпадку значэнне для поля рэдьюсера можа быць прадстаўлена ў выглядзе наступнага аб'екта:

jsx{reducer, prepare}

Давайце адчынём наш файл productsSlice.js і зменім код для рэдьюсера productAdded. Цяпер гэты кавалачак кода:

products/ProductSlice.jsproductAdded(state, action) {
  state.push(action.payload)
},

Мы зменім на наступны, у якім функцыя reducer будзе займацца абнаўленнем стэйта ў store, а prepare - вяртаць аб'ект payload з згенераваным id і іншымі нашымі данымі:

products/ProductSlice.jsproductAdded: {
  reducer(state, action) {
    state.push(action.payload)
  },
  prepare(name, desc, price, amount) {
    return {
      payload: {
        id: nanoid(),
        name,
        desc,
        price,
        amount,
      },
    }
  },
},

Прыколькі цяпер мы будзем генераваць id тут, а не ў кампаненце, давайце дадамо nanoid у імпарт:

products/ProductSlice.jsimport { createSlice, nanoid } from '@reduxjs/toolkit'

Напослед унясем змены ў NewProductForm.jsx. Замест радка:

products/NewProductForm.jsxdispatch(productAdded({
  id: nanoid(), name, desc, price, amount
}))

У нас будзе такая, у якой мы проста праз коску перададзім неабходныя нам даныя (не забудзьце ў гэтым файле прыбраць nanoid з імпарту):

products/NewProductForm.jsxdispatch(productAdded(name, desc, price, amount))

Запусцім прыкладанне, затым створым новы прадукт і пераканаемся, што мы нічога не паламалі.

Задание 1

Адчынiце ваша прыкладанне са студэнтамі. У файле StudentsSlice.js перапішыце ваш рэдьюсер studentAdded такім чынам, каб ён быў у выглядзе аб'екта {reducer, prepare}, як паказана ў уроку.

Задание 2

Унясіце адпаведныя змены ў файл NewStudentForm.jsx, як паказана ў уроку. Запусціце прыкладанне і пераканайцеся, што ўсё працуе як і раней.