Quellcode durchsuchen

Add promiseWatcher, fullProfilePageWatcher, fullPageAboutUserWatcher

LenDoc vor 1 Jahr
Ursprung
Commit
0467b55eef

+ 29 - 0
package-lock.json

@@ -34,6 +34,7 @@
         "redux": "^4.1.2",
         "redux-saga": "^1.1.3",
         "redux-thunk": "^2.4.1",
+        "saga": "^4.0.0-alpha",
         "web-vitals": "^2.1.4"
       },
       "devDependencies": {
@@ -14805,6 +14806,19 @@
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
+    "node_modules/saga": {
+      "version": "4.0.0-alpha",
+      "resolved": "https://registry.npmjs.org/saga/-/saga-4.0.0-alpha.tgz",
+      "integrity": "sha512-zlCIMLPaurw1bBBmGkKTyDR8j1f2pkYZGP1+pn46nZT+QiMD77gpaYjOtA8eIE4urPdOacmtT9pcEKJ/woIV6Q==",
+      "dependencies": {
+        "tslib": "^1.9.3"
+      }
+    },
+    "node_modules/saga/node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+    },
     "node_modules/sanitize.css": {
       "version": "13.0.0",
       "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz",
@@ -27798,6 +27812,21 @@
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
+    "saga": {
+      "version": "4.0.0-alpha",
+      "resolved": "https://registry.npmjs.org/saga/-/saga-4.0.0-alpha.tgz",
+      "integrity": "sha512-zlCIMLPaurw1bBBmGkKTyDR8j1f2pkYZGP1+pn46nZT+QiMD77gpaYjOtA8eIE4urPdOacmtT9pcEKJ/woIV6Q==",
+      "requires": {
+        "tslib": "^1.9.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "1.14.1",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+        }
+      }
+    },
     "sanitize.css": {
       "version": "13.0.0",
       "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz",

+ 1 - 0
package.json

@@ -30,6 +30,7 @@
     "redux": "^4.1.2",
     "redux-saga": "^1.1.3",
     "redux-thunk": "^2.4.1",
+    "saga": "^4.0.0-alpha",
     "web-vitals": "^2.1.4"
   },
   "scripts": {

+ 2 - 2
src/App.js

@@ -4,7 +4,7 @@ import { Router, Route, Redirect, Switch } from 'react-router-dom'
 import React from 'react'
 import { store } from './redux/reducers'
 import 'antd/dist/antd.css'
-import { actionFullProfilePage } from './redux/thunk'
+import { actionFullProfilePage } from './redux/saga'
 import { actionFullAllGetPosts } from './actions'
 
 import { CShowHeader } from './pages/header'
@@ -19,7 +19,7 @@ function App() {
   if (store.getState().auth?.token) {
     console.log('токен', store.getState().auth?.payload?.sub?.id)
     store.dispatch(
-      actionFullProfilePage(store.getState().auth?.payload?.sub?.id)
+      actionFullProfilePage()
     )
     }
   return (

+ 49 - 27
src/actions/index.js

@@ -2,15 +2,17 @@ import { ConsoleSqlOutlined } from '@ant-design/icons'
 import {
   actionFullProfilePageUser,
   actionFullProfilePage,
-} from '../redux/thunk'
+} from '../redux/saga'
 import { actionFeedTypeCount } from '../redux/reducers/feed/feedReducer'
 import { actionFeedType } from '../redux/reducers/feed/feedReducer'
 import { actionExploreTypeCount } from '../redux/reducers/explore/exploreReducer'
 import { actionClearExplorePosts } from '../redux/reducers/explore/exploreReducer'
 import { actionExploreType } from '../redux/reducers/explore/exploreReducer'
 import { actionClearFeedPosts } from '../redux/reducers/feed/feedReducer'
-
+import {actionProfilePageDataType} from '../redux/reducers/profileData/profileReducer'
 import { history } from '../helpers'
+import{promiseWorker} from '../redux/saga'
+import { all, put, takeEvery, takeLatest, takeLeading, select,call } from 'redux-saga/effects'; //
 export const actionAuthLogin = (token) => ({ type: 'AUTH_LOGIN', token })
 export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
 export const getGQL = (url) => (query, variables) =>
@@ -71,16 +73,20 @@ export const actionRejected = (name, error) => ({
   status: 'REJECTED',
   error,
 })
-export const actionPromise = (name, promise) => async (dispatch) => {
-  dispatch(actionPending(name))
-  try {
-    let payload = await promise
-    dispatch(actionFulfilled(name, payload))
-    return payload
-  } catch (error) {
-    dispatch(actionRejected(name, error))
-  }
-}
+// export const actionPromise = (name, promise) => async (dispatch) => {
+//   dispatch(actionPending(name))
+//   try {
+//     let payload = await promise
+//     dispatch(actionFulfilled(name, payload))
+//     return payload
+//   } catch (error) {
+//     dispatch(actionRejected(name, error))
+//   }
+// }
+const actionPromise = (name, promise) =>
+  ({ type: 'PROMISE_START', name, promise })
+
+
 export const actionAboutMe = (_id) =>
   actionPromise(
     'aboutMe',
@@ -99,21 +105,37 @@ export const actionAboutMe = (_id) =>
     ),
   )
 
-export const actionFullLogin = (login, password) => async (dispatch) => {
-  let token = await dispatch(
-    actionPromise(
-      'auth',
-      gql(
-        ` query login($login:String!, $password:String!){
-            login(login:$login, password:$password)} `,
-        { login, password },
-      ),
-    ),
-  )
-  if (token) {
-    await dispatch(actionAuthLogin(token))
-  }
-}
+ export const actionFullLogin = (login, password) =>  //упрощенный action для саги
+    ({type: 'FULL_LOGIN', login, password})
+    
+export const actionLogin = (login, password) => { //функция, которая возвращает результат actionPromise
+    return actionPromise(
+        "auth",
+        gql(
+            `query log($login:String, $password:String) {
+              login(login:$login, password:$password)
+             }`,
+            { login, password }
+        )
+    );
+};
+
+
+// export const actionFullLogin = (login, password) => async (dispatch) => {
+//   let token = await dispatch(
+//     actionPromise(
+//       'auth',
+//       gql(
+//         ` query login($login:String!, $password:String!){
+//             login(login:$login, password:$password)} `,
+//         { login, password },
+//       ),
+//     ),
+//   )
+//   if (token) {
+//     await dispatch(actionAuthLogin(token))
+//   }
+// }
 
 export const actionRegister = (login, password) =>
   actionPromise(

+ 8 - 3
src/components/Header.js

@@ -1,5 +1,5 @@
 import user from '../materials/user.png'
-import { actionFullProfilePageUser } from '../redux/thunk'
+import { actionFullProfilePageUser } from '../redux/saga'
 import { Avatar, Button } from 'antd'
 import { CSearch } from './Search_Users'
 import { Link } from 'react-router-dom'
@@ -40,7 +40,12 @@ export const Explore = () => (
   </Link>
 )
 const User = ({ my_Id, aboutMe: { _id, login, avatar } = {}, onMyPage }) => {
-  useEffect(() => onMyPage(_id), [_id])
+  console.log('_id in user', _id)
+  
+  // useEffect(() => {
+  //   if (my_Id)
+  //     onMyPage(my_Id)
+  // }, [my_Id])
   return (
     <Link to={`/profile/${_id}`}>
       {avatar?.url ? (
@@ -57,5 +62,5 @@ export const CUser = connect(
     my_Id: state.auth?.payload?.sub?.id,
     aboutMe: state.profileData.aboutMe,
   }),
-  { onMyPage: actionFullProfilePageUser },
+  // { onMyPage: actionFullProfilePageUser },
 )(User)

+ 1 - 1
src/components/Like.js

@@ -8,7 +8,7 @@ import { LinkToUser } from './LinkToUser'
 import {
   actionAddFullLikeFeed,
   actionDeleteFullLikeFeed,
-} from '../redux/thunk'
+} from '../redux/saga'
 import { connect } from 'react-redux'
 
 export const Likes = ({ likes }) => {

+ 1 - 1
src/components/LoginRegisterLogout.js

@@ -4,7 +4,7 @@ import React, { useState } from 'react'
 import { connect } from 'react-redux'
 import { Button, Input, Checkbox, Form } from 'antd'
 import { Link } from 'react-router-dom'
-import { actionClearUserData } from '../redux/thunk'
+import { actionClearUserData } from '../redux/saga'
 import { message } from 'antd'
 import { useEffect } from 'react'
 

+ 1 - 1
src/components/Post.js

@@ -18,7 +18,7 @@ import { ConstructorModal } from '../helpers'
 import React, { useState, useEffect } from 'react'
 import {
   actionAddFullCommentFeed,
-} from '../redux/thunk'
+} from '../redux/saga'
 import { LinkToUser } from './LinkToUser'
 import { MyCarousel } from './Carousel'
 const EditMyPost = ({ _id }) => {

+ 1 - 1
src/components/Search_Users.js

@@ -5,7 +5,7 @@ import user from '../materials/user.png'
 import { actionSearchUser } from '../actions'
 import {UserOutlined } from '@ant-design/icons'
 
-import { actionFullProfilePageUser } from '../redux/thunk'
+import { actionFullProfilePageUser } from '../redux/saga'
 import LinkToUser from './LinkToUser'
 export const ResultUserFind = ({
   userFind = [],

+ 1 - 1
src/pages/feedPosts/index.js

@@ -19,7 +19,7 @@ import {
   actionAddFullLikeFeed,
   actionDeleteFullLikeFeed,
  
-} from '../../redux/thunk'
+} from '../../redux/saga'
 import {actionFullClearFeedPosts} from '../../redux/reducers/feed/feedReducer'
 import { Link } from 'react-router-dom'
 import { Provider, connect } from 'react-redux'

+ 1 - 1
src/pages/profilePage/index.js

@@ -5,7 +5,7 @@ import { Card } from '../../components/PostCard'
 import ListOfUsers from '../../components/ListOfUsers'
 import { connect } from 'react-redux'
 import { Avatar, Button } from 'antd'
-import { actionFullProfilePageUser } from '../../redux/thunk'
+import { actionFullProfilePageUser } from '../../redux/saga'
 import { Row, Col } from 'antd'
 import { CSubscribe } from '../../components/Subscribe'
 import { CEditSetting } from '../setting'

+ 22 - 2
src/redux/reducers/index.js

@@ -8,7 +8,14 @@ import { profileUserReducer } from './profileUserPage/profileUserReducer'
 import { feedReducer } from './feed/feedReducer'
 import { postReducer } from './post/postReducer'
 import { exploreReducer } from './explore/exploreReducer'
-
+import {
+  promiseWatcher, fullProfilePageWatcher,
+  loginWatcher, fullPageAboutUserWatcher,
+  feedWatcher
+} from '../saga'
+import createSagaMiddleware from 'redux-saga'; //функция по созданию middleware
+import { all, put, takeEvery, takeLatest, takeLeading, select } from 'redux-saga/effects'; //
+const sagaMiddleware = createSagaMiddleware() 
 
 export const store = createStore(
   combineReducers({
@@ -20,5 +27,18 @@ export const store = createStore(
     post: postReducer,
     explore: exploreReducer
   }),
-  applyMiddleware(thunk),
+  applyMiddleware(sagaMiddleware)
 )
+function* rootSaga(){ 
+  yield all([ 
+      //тут обычно прописываются саги, описывающие виды экшонов, которые требуют обработки
+      promiseWatcher(), //для пустого старта саги закомментируйте эти строки.
+                        //таким образом вы проверите правильность подключения redux-saga
+      fullProfilePageWatcher(),
+      loginWatcher(),
+    fullPageAboutUserWatcher(),
+    
+    // feedWatcher()
+  ])
+}
+sagaMiddleware.run(rootSaga)

+ 208 - 0
src/redux/saga/index.js

@@ -0,0 +1,208 @@
+
+import {
+    actionAboutMe,
+    actionAllPostsUser,
+    actionAboutUser,
+    actionPostsFeed,
+    actionPostsFeedCount,
+    actionOnePost,
+    actionAddComment,
+    actionAddLike,
+    actionDeleteLike,
+    actionPostsCount,
+    actionAuthLogout,
+  actionAllClearPromise,
+  actionLogin,
+  actionAuthLogin,
+  
+  } from '../../actions'
+import { history } from '../../helpers'
+  import{actionClearDataUserType} from '../reducers/profileUserPage/profileUserReducer'
+import { actionProfilePageDataType } from '../reducers/profileData/profileReducer'
+import { actionFullAllGetPosts } from '../../actions'
+import {
+  actionAddLikePostInTape,
+  actionDeleteLikePostInTape,
+  actionAddCommentPostInTape,
+  actionClearFeedPosts,
+  actionFeedType
+} from '../reducers/feed/feedReducer'
+import { actionProfilePageDataTypeUser } from '../reducers/profileUserPage/profileUserReducer'
+import { actionRemoveDataAboutMe } from '../reducers/profileData/profileReducer'
+import { all, put, takeEvery, takeLatest, takeLeading, select,call } from 'redux-saga/effects'; //
+import {actionPending,actionFulfilled,actionRejected} from '../../actions'
+
+
+  //promise
+ export function* promiseWorker(action){ //это типа actionPromise который thunk
+    const {name, promise} = action
+    yield put(actionPending(name)) //это как dispatch
+    try {
+        let data = yield promise //а это как await
+        yield put(actionFulfilled(name, data))
+        return data //а этот результать можно забрать через yield call(promiseWorker, actionPromise(......) /*какой-то объект action*/)
+    }
+    catch (error) {
+        yield put(actionRejected(name, error))
+    }
+  }
+  
+  export function* promiseWatcher(){
+    yield takeEvery('PROMISE_START', promiseWorker)
+}
+
+//login
+function* loginWorker({login, password}){ //обработчик экшона FULL_LOGIN
+  let token = yield call(promiseWorker,actionLogin(login, password)) //dispatch(actionLogin(login, password));
+  if (token) {
+      yield put(actionAuthLogin(token));
+  }
+}
+export function* loginWatcher() {
+yield takeEvery("'FULL_LOGIN'", loginWorker)
+
+}
+//profile page about me
+export const actionFullProfilePage = () =>
+({
+    type:"FULLPROFILE_PAGE",
+})
+
+function* fullProfilePageWorker() {
+  const { auth } = yield select()
+  if (auth?.payload?.sub?.id) {
+    const aboutMe = yield call(promiseWorker, actionAboutMe(auth?.payload?.sub.id))
+    if (aboutMe) {
+      yield put(actionProfilePageDataType(aboutMe))
+      console.log('about me _id',aboutMe?._id)
+      yield put(actionFullProfilePageUser(aboutMe?._id))
+    }
+  }
+}
+
+
+export function* fullProfilePageWatcher() {
+  yield takeEvery("FULLPROFILE_PAGE", fullProfilePageWorker)
+}
+
+//aboutUser
+//full profile user
+
+export const actionFullProfilePageUser = (_id) =>
+  ({ type: "USER_PAGE", _id })
+  
+function* fullPageAboutUserWorker({ _id }) {
+  console.log('_id ',  _id)
+
+  const aboutUser = yield call(promiseWorker, actionAboutUser(_id))
+  console.log('about user',  aboutUser)
+  const allPosts = yield call(promiseWorker, actionAllPostsUser(_id))
+  if (aboutUser && allPosts) {
+    yield put(actionProfilePageDataTypeUser(aboutUser, allPosts))
+
+  }
+}
+
+export function* fullPageAboutUserWatcher() {
+  yield takeLeading("USER_PAGE", fullPageAboutUserWorker)
+}
+
+function* feedWorker() {
+  const {
+    feed: { postsFeed, postsFeedCount },
+    profileData: { aboutMe },
+    
+  } = yield select()
+  let myFollowing =
+    aboutMe?.following && aboutMe?.following?.map(({ _id }) => _id)
+  const myId = yield select().auth.payload?.sub?.id
+  if (!myFollowing)
+  yield put(actionFullProfilePage(myId))
+  // await dispatch(actionFullProfilePage(myId))
+myFollowing = yield select().profileData.aboutMe?.following?.map(({ _id }) => _id)
+  console.log('myFollowing ', myFollowing)
+  if (postsFeed.length !== (postsFeedCount ? postsFeedCount : 1)) {
+    const newPosts = yield call(promiseWorker, 
+      actionPostsFeed([...(myFollowing || []), myId], postsFeed.length),
+    )
+    console.log('newPosts', newPosts)
+    const newPostsFeedCount = yield call(promiseWorker, (
+      actionPostsFeedCount([...(myFollowing || []), myId])))
+    
+    if (newPosts && newPostsFeedCount) {
+      console.log('newPosts', newPosts)
+      yield put(actionFeedType(newPosts, newPostsFeedCount))
+    }
+  }
+  // const aboutMe = yield call(promiseWorker, actionAboutMe(_id))
+  // if (aboutMe)
+  // yield put(actionProfilePageDataType(aboutMe))
+}
+
+
+export function* feedWatcher() {
+  yield takeEvery("FEED_POSTS", feedWorker)
+}
+
+//feed
+
+export const actionAddFullLikeFeed = (postId) => async (dispatch, getState) => {
+    await dispatch(actionAddLike(postId))
+    const {
+      promise: {
+        addLike: { status },
+      },
+    } = getState()
+    if (status === 'FULFILLED') {
+      const onePost = await dispatch(actionOnePost(postId))
+      if (onePost) await dispatch(actionAddLikePostInTape(postId))
+    }
+}
+  
+export const actionDeleteFullLikeFeed = (likeId, postId) => async (
+    dispatch,
+    getState,
+  ) => {
+    await dispatch(actionDeleteLike(likeId, postId))
+    const {
+      promise: {
+        deleteLike: { status },
+      },
+    } = getState()
+    if (status === 'FULFILLED') {
+      const onePost = await dispatch(actionOnePost(postId))
+      if (onePost) await dispatch(actionDeleteLikePostInTape(likeId, postId))
+    }
+  }
+
+  //comment
+export const actionAddFullCommentFeed = (postId, newResult) => async (
+    dispatch,
+    getState,
+  ) => {
+    await dispatch(actionAddComment(postId, newResult))
+    const {
+      promise: {
+        addComment: { status },
+      },
+    } = getState()
+    if (status === 'FULFILLED') {
+      const onePost = await dispatch(actionOnePost(postId))
+      if (onePost) await dispatch(actionAddCommentPostInTape(postId, newResult))
+    }
+    // await dispatch(actionOnePost(postId));
+}
+
+//clear user data after log out
+export const actionClearUserData = () => async (dispatch) => {
+    const logOut = await dispatch(actionAuthLogout())
+    if (logOut) {
+      history.push('/input')
+      await dispatch(actionClearDataUserType())
+      await dispatch(actionClearFeedPosts())
+      await dispatch(actionRemoveDataAboutMe())
+      await dispatch(actionAllClearPromise())
+      
+    }
+  }
+

+ 0 - 115
src/redux/thunk/index.js

@@ -1,115 +0,0 @@
-
-import {
-    actionAboutMe,
-    actionAllPostsUser,
-    actionAboutUser,
-    actionPostsFeed,
-    actionPostsFeedCount,
-    actionOnePost,
-    actionAddComment,
-    actionAddLike,
-    actionDeleteLike,
-    actionPostsCount,
-    actionAuthLogout,
-    actionAllClearPromise
-  } from '../../actions'
-import { history } from '../../helpers'
-  import{actionClearDataUserType} from '../reducers/profileUserPage/profileUserReducer'
-import { actionProfilePageDataType } from '../reducers/profileData/profileReducer'
-import { actionFullAllGetPosts } from '../../actions'
-import {
-  actionAddLikePostInTape,
-  actionDeleteLikePostInTape,
-  actionAddCommentPostInTape,
-  actionClearFeedPosts
-} from '../reducers/feed/feedReducer'
-import { actionProfilePageDataTypeUser } from '../reducers/profileUserPage/profileUserReducer'
-import {actionRemoveDataAboutMe} from '../reducers/profileData/profileReducer'
-//profile page about me
-export const actionFullProfilePage = (_id) => async (dispatch) => {
-    const aboutMe = await dispatch(actionAboutMe(_id))
-    if (aboutMe) {
-    await dispatch(actionProfilePageDataType(aboutMe))
-  }
- 
-  }
-
-export const actionAddFullLikeFeed = (postId) => async (dispatch, getState) => {
-    await dispatch(actionAddLike(postId))
-    const {
-      promise: {
-        addLike: { status },
-      },
-    } = getState()
-    if (status === 'FULFILLED') {
-      const onePost = await dispatch(actionOnePost(postId))
-      if (onePost) await dispatch(actionAddLikePostInTape(postId))
-    }
-}
-  
-export const actionDeleteFullLikeFeed = (likeId, postId) => async (
-    dispatch,
-    getState,
-  ) => {
-    await dispatch(actionDeleteLike(likeId, postId))
-    const {
-      promise: {
-        deleteLike: { status },
-      },
-    } = getState()
-    if (status === 'FULFILLED') {
-      const onePost = await dispatch(actionOnePost(postId))
-      if (onePost) await dispatch(actionDeleteLikePostInTape(likeId, postId))
-    }
-  }
-
-  //comment
-export const actionAddFullCommentFeed = (postId, newResult) => async (
-    dispatch,
-    getState,
-  ) => {
-    await dispatch(actionAddComment(postId, newResult))
-    const {
-      promise: {
-        addComment: { status },
-      },
-    } = getState()
-    if (status === 'FULFILLED') {
-      const onePost = await dispatch(actionOnePost(postId))
-      if (onePost) await dispatch(actionAddCommentPostInTape(postId, newResult))
-    }
-    // await dispatch(actionOnePost(postId));
-}
-
-//clear user data after log out
-export const actionClearUserData = () => async (dispatch) => {
-    const logOut = await dispatch(actionAuthLogout())
-    if (logOut) {
-      history.push('/input')
-      await dispatch(actionClearDataUserType())
-      await dispatch(actionClearFeedPosts())
-      await dispatch(actionRemoveDataAboutMe())
-      await dispatch(actionAllClearPromise())
-      
-    }
-  }
-
-
-//full profile user
-export const actionFullProfilePageUser = (_id) => async (dispatch, getState) => {
-  const {
-    profilePage
-  } = getState()
-  console.log('тут айдиии', _id)
-  if (_id != undefined) {
-    const aboutUser = await dispatch(actionAboutUser(_id))
-    const allPosts = await dispatch(actionAllPostsUser(_id))
-    await dispatch(actionPostsCount(_id))
-    if (aboutUser && allPosts) {
-      await dispatch(actionProfilePageDataTypeUser(aboutUser, allPosts))
-    }
-  }
-  _id = getState().profilePage.aboutUser?._id
-  console.log('тут айдиии после', _id)
-
-  }