hw_19_03_cart_reducer.html 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <header>cart reducer</header>
  2. <body>
  3. <div id="testDiv">
  4. Test
  5. </div>
  6. <script>
  7. function cartReducer(state = {}, action) { // диспетчер обработки
  8. switch (action.type) {
  9. case 'CART_ADD':
  10. if (action.count >= 0) {
  11. let newState = { ...state };
  12. let { count } = state[action.good._id] ?? { count: 0 };
  13. newState[action.good._id] = { count: action.count + count, good: { ...action.good } }
  14. return newState;
  15. }
  16. case 'CART_SUB':
  17. if (action.count >= 0) {
  18. let newState = { ...state };
  19. let { count } = state[action.good._id] ?? { count: 0 };
  20. if (count >= action.count) {
  21. newState[action.good._id] = { count: action.count - count, good: { ...action.good } }
  22. return newState;
  23. }
  24. }
  25. break;
  26. case 'CART_DEL':
  27. {
  28. let newState = { ...state };
  29. delete newState[action.good._id];
  30. return newState;
  31. }
  32. case 'CART_SET':
  33. {
  34. let newState = { ...state };
  35. newState[action.good._id] = { count: action.count, good: { ...action.good } };
  36. return newState;
  37. }
  38. case 'CART_CLEAR':
  39. return {};
  40. }
  41. return state;
  42. }
  43. function createStore(reducer) {
  44. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  45. let cbs = [] //массив подписчиков
  46. const getState = () => state //функция, возвращающая переменную из замыкания
  47. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  48. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  49. function dispatch(action) {
  50. if (typeof action === 'function') { //если action - не объект, а функция
  51. return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  52. }
  53. const newState = reducer(state, action) //пробуем запустить редьюсер
  54. if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  55. state = newState //если смог, то обновляем state
  56. for (let cb of cbs) cb() //и запускаем подписчиков
  57. }
  58. }
  59. return {
  60. getState, //добавление функции getState в результирующий объект
  61. dispatch,
  62. subscribe //добавление subscribe в объект
  63. }
  64. }
  65. const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', count: count, good: good });
  66. const actionCartSub = (good, count = 1) => ({ type: 'CART_SUB', count, good }); //Уменьшение количества товара. Должен уменьшать количество товара в state, или удалять его если количество будет 0 или отрицательным
  67. const actionCartDel = (good) => ({ type: 'CART_DEL', good }); //Удаление товара. Должен удалять ключ из state
  68. const actionCartSet = (good, count = 1) => ({ type: 'CART_SET', count, good }); //Задание количества товара. В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху (или создает новый ключ, если в корзине товара не было). Если count 0 или отрицательное число - удаляем ключ из корзины;
  69. const actionCartClear = () => ({ type: 'CART_CLEAR' }); //Очистка корзины. state должен стать пустым объектом {}
  70. const store = createStore(cartReducer)
  71. store.subscribe(() => {
  72. console.log(store.getState())
  73. });
  74. store.dispatch(actionCartAdd({ _id: 'пиво', price: 50 }))
  75. // {пиво: {good: {_id: 'пиво', price: 50}, count: 1}}
  76. store.dispatch(actionCartAdd({ _id: 'чипсы', price: 75 }))
  77. // {
  78. // {пиво: {good: {_id: 'пиво', price: 50}, count: 1},
  79. // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 1},
  80. //}
  81. store.dispatch(actionCartAdd({ _id: 'пиво', price: 50 }, 5))
  82. // {
  83. // {пиво: {good: {_id: 'пиво', price: 50}, count: 6},
  84. // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 1},
  85. //}
  86. store.dispatch(actionCartSet({ _id: 'чипсы', price: 75 }, 2))
  87. // {
  88. // {пиво: {good: {_id: 'пиво', price: 50}, count: 6},
  89. // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 2},
  90. //}
  91. store.dispatch(actionCartSub({ _id: 'пиво', price: 50 }, 4))
  92. // {
  93. // {пиво: {good: {_id: 'пиво', price: 50}, count: 2},
  94. // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 2},
  95. //}
  96. store.dispatch(actionCartDel({ _id: 'чипсы', price: 75 }))
  97. // {
  98. // {пиво: {good: {_id: 'пиво', price: 50}, count: 2},
  99. //}
  100. store.dispatch(actionCartClear()) // {}
  101. </script>
  102. </body>