浏览代码

saga added to shop

ivar_n 2 年之前
父节点
当前提交
4becd49154

+ 18 - 0
js/22_react_cw/elements/src/App.js

@@ -406,6 +406,24 @@ const PhoneBook = ({people=defaultPeople, onSave}) => {
 }
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 function App() {
     const [country, setCountry] = useState('UA')

+ 154 - 1
js/24_react_shop/react_shop/package-lock.json

@@ -5,7 +5,7 @@
   "requires": true,
   "packages": {
     "": {
-      "name": "hw",
+      "name": "shop",
       "version": "0.1.0",
       "dependencies": {
         "@testing-library/jest-dom": "^5.16.1",
@@ -19,6 +19,7 @@
         "react-router-dom": "^5.3.0",
         "react-scripts": "5.0.0",
         "redux": "^4.1.2",
+        "redux-saga": "^1.1.3",
         "redux-thunk": "^2.4.1",
         "sass": "^1.45.1",
         "web-vitals": "^2.1.2"
@@ -2709,6 +2710,53 @@
         "react": "^16.8.0 || ^17.0.0-rc.1"
       }
     },
+    "node_modules/@redux-saga/core": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz",
+      "integrity": "sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg==",
+      "dependencies": {
+        "@babel/runtime": "^7.6.3",
+        "@redux-saga/deferred": "^1.1.2",
+        "@redux-saga/delay-p": "^1.1.2",
+        "@redux-saga/is": "^1.1.2",
+        "@redux-saga/symbols": "^1.1.2",
+        "@redux-saga/types": "^1.1.0",
+        "redux": "^4.0.4",
+        "typescript-tuple": "^2.2.1"
+      }
+    },
+    "node_modules/@redux-saga/deferred": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz",
+      "integrity": "sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ=="
+    },
+    "node_modules/@redux-saga/delay-p": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz",
+      "integrity": "sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g==",
+      "dependencies": {
+        "@redux-saga/symbols": "^1.1.2"
+      }
+    },
+    "node_modules/@redux-saga/is": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz",
+      "integrity": "sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w==",
+      "dependencies": {
+        "@redux-saga/symbols": "^1.1.2",
+        "@redux-saga/types": "^1.1.0"
+      }
+    },
+    "node_modules/@redux-saga/symbols": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz",
+      "integrity": "sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ=="
+    },
+    "node_modules/@redux-saga/types": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz",
+      "integrity": "sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg=="
+    },
     "node_modules/@restart/hooks": {
       "version": "0.4.5",
       "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.5.tgz",
@@ -13676,6 +13724,14 @@
         "@babel/runtime": "^7.9.2"
       }
     },
+    "node_modules/redux-saga": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/redux-saga/-/redux-saga-1.1.3.tgz",
+      "integrity": "sha512-RkSn/z0mwaSa5/xH/hQLo8gNf4tlvT18qXDNvedihLcfzh+jMchDgaariQoehCpgRltEm4zHKJyINEz6aqswTw==",
+      "dependencies": {
+        "@redux-saga/core": "^1.1.3"
+      }
+    },
     "node_modules/redux-thunk": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
@@ -15337,6 +15393,27 @@
         "node": ">=4.2.0"
       }
     },
+    "node_modules/typescript-compare": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz",
+      "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==",
+      "dependencies": {
+        "typescript-logic": "^0.0.0"
+      }
+    },
+    "node_modules/typescript-logic": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz",
+      "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q=="
+    },
+    "node_modules/typescript-tuple": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz",
+      "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==",
+      "dependencies": {
+        "typescript-compare": "^0.0.2"
+      }
+    },
     "node_modules/unbox-primitive": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@@ -18332,6 +18409,53 @@
         "@babel/runtime": "^7.6.2"
       }
     },
+    "@redux-saga/core": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz",
+      "integrity": "sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg==",
+      "requires": {
+        "@babel/runtime": "^7.6.3",
+        "@redux-saga/deferred": "^1.1.2",
+        "@redux-saga/delay-p": "^1.1.2",
+        "@redux-saga/is": "^1.1.2",
+        "@redux-saga/symbols": "^1.1.2",
+        "@redux-saga/types": "^1.1.0",
+        "redux": "^4.0.4",
+        "typescript-tuple": "^2.2.1"
+      }
+    },
+    "@redux-saga/deferred": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz",
+      "integrity": "sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ=="
+    },
+    "@redux-saga/delay-p": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz",
+      "integrity": "sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g==",
+      "requires": {
+        "@redux-saga/symbols": "^1.1.2"
+      }
+    },
+    "@redux-saga/is": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz",
+      "integrity": "sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w==",
+      "requires": {
+        "@redux-saga/symbols": "^1.1.2",
+        "@redux-saga/types": "^1.1.0"
+      }
+    },
+    "@redux-saga/symbols": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz",
+      "integrity": "sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ=="
+    },
+    "@redux-saga/types": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz",
+      "integrity": "sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg=="
+    },
     "@restart/hooks": {
       "version": "0.4.5",
       "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.5.tgz",
@@ -26246,6 +26370,14 @@
         "@babel/runtime": "^7.9.2"
       }
     },
+    "redux-saga": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/redux-saga/-/redux-saga-1.1.3.tgz",
+      "integrity": "sha512-RkSn/z0mwaSa5/xH/hQLo8gNf4tlvT18qXDNvedihLcfzh+jMchDgaariQoehCpgRltEm4zHKJyINEz6aqswTw==",
+      "requires": {
+        "@redux-saga/core": "^1.1.3"
+      }
+    },
     "redux-thunk": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
@@ -27480,6 +27612,27 @@
       "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
       "peer": true
     },
+    "typescript-compare": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz",
+      "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==",
+      "requires": {
+        "typescript-logic": "^0.0.0"
+      }
+    },
+    "typescript-logic": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz",
+      "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q=="
+    },
+    "typescript-tuple": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz",
+      "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==",
+      "requires": {
+        "typescript-compare": "^0.0.2"
+      }
+    },
     "unbox-primitive": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",

+ 1 - 0
js/24_react_shop/react_shop/package.json

@@ -14,6 +14,7 @@
     "react-router-dom": "^5.3.0",
     "react-scripts": "5.0.0",
     "redux": "^4.1.2",
+    "redux-saga": "^1.1.3",
     "redux-thunk": "^2.4.1",
     "sass": "^1.45.1",
     "web-vitals": "^2.1.2"

+ 79 - 23
js/24_react_shop/react_shop/src/App.js

@@ -1,4 +1,4 @@
-import React, {useState, useEffect, useRef, Component} from 'react';
+import React, {useState, useEffect, useRef, Component, createRef} from 'react';
 import logoDefault from './logo.svg';
 import cartImg from './cart.svg';
 import 'bootstrap/dist/css/bootstrap.min.css';
@@ -6,6 +6,10 @@ import './App.scss';
 import {Provider, connect}   from 'react-redux';
 import {createStore, combineReducers, applyMiddleware} from 'redux';
 import thunk from 'redux-thunk';
+import createSagaMiddleware from 'redux-saga';
+import {all, takeEvery, put, call, take, select} from 'redux-saga/effects';
+
+
 import {Router, Route, Link, Redirect, Switch} from 'react-router-dom';
 import createHistory from "history/createBrowserHistory";
 
@@ -207,17 +211,18 @@ const actionRejected = (name, error) => ({type: 'PROMISE', status: 'REJECTED', n
 
 
 const actionPromise = (name, promise) => (
-  async (dispatch) => {
-      dispatch(actionPending(name))
-      try { 
-          let data = await promise
-          dispatch(actionResolved(name, data))
-          return data
-      }
-      catch(error){
-          dispatch(actionRejected(name, error))
-      }
-  }
+  {type: 'PROMISE_START', name, promise}
+  // async (dispatch) => {
+  //     dispatch(actionPending(name))
+  //     try { 
+  //         let data = await promise
+  //         dispatch(actionResolved(name, data))
+  //         return data
+  //     }
+  //     catch(error){
+  //         dispatch(actionRejected(name, error))
+  //     }
+  // }
 )
 
 
@@ -276,12 +281,13 @@ const getGQL = url => (
   )
   
   const actionFullLogin = (login, password) => (
-      async (dispatch) => {
-          let token = await dispatch(actionLogin(login, password))
-          if (token) {
-              dispatch(actionAuthLogin(token))
-          }
-      }
+    {type: 'FULL_LOGIN', login, password}
+      // async (dispatch) => {
+      //     let token = await dispatch(actionLogin(login, password))
+      //     if (token) {
+      //         dispatch(actionAuthLogin(token))
+      //     }
+      // }
   )
     
   const actionRegister = (login, password) => (
@@ -382,14 +388,61 @@ const getGQL = url => (
 
 
 
+// const store = createStore(  combineReducers({ promise: promiseReducer, 
+//                                               auth: authReducer, 
+//                                               cart: cartReducer}),
+//                             applyMiddleware(thunk))
+
+const sagaMiddleware = createSagaMiddleware()   
 const store = createStore(  combineReducers({ promise: promiseReducer, 
-                                              auth: authReducer, 
-                                              cart: cartReducer}),
-                            applyMiddleware(thunk))
-store.subscribe(() => console.log(store.getState()))
+                              auth: authReducer, 
+                              cart: cartReducer}),
+                            applyMiddleware(sagaMiddleware))                        
 
 
-store.dispatch(actionRootCats())
+
+//  аналог actionPromise
+function* promiseWorker(action) {
+  const {name, promise} = action
+    yield put(actionPending(name))
+    try { 
+          let data = yield promise
+          yield put(actionResolved(name, data))
+        return data
+      }
+      catch(error){
+          yield put(actionRejected(name, error))
+      }     
+}
+
+function* promiseWatcher() {
+  // запуск worker для каждого экшна типа промис старт,
+  // в обработчмк приходит результат функции с промис старт
+  yield takeEvery('PROMISE_START', promiseWorker)
+}
+
+
+function* loginWorker(action) {
+  const {login, password} = action
+    // аналог вложенного диспатча вложенного санка
+    let token = yield call(promiseWorker, actionLogin(login, password))
+    if (token) {
+      yield put(actionAuthLogin(token))
+    }    
+}
+
+function* loginWatcher() {
+  yield takeEvery('FULL_LOGIN', loginWorker)
+}
+
+function* rootSaga() {
+  yield all([
+    promiseWatcher(),
+    loginWatcher()
+  ])
+}
+
+sagaMiddleware.run(rootSaga)
 
 
 
@@ -397,6 +450,9 @@ store.dispatch(actionRootCats())
 
 
 
+store.subscribe(() => console.log(store.getState()))
+store.dispatch(actionRootCats())
+
 
 const Logo = ({logo=logoDefault}) => (
   <Link to='/' className="Logo">