From 639c952c2cc09a1a3c533b0dfc77a258645f4711 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Mon, 20 Sep 2021 11:56:20 +0700 Subject: [PATCH] moved comments load to hook --- src/components/boris/BorisComments/index.tsx | 25 +++++- src/components/comment/Comment/index.tsx | 4 +- .../comment/CommentContent/index.tsx | 2 +- src/components/node/NodeBottomBlock/index.tsx | 11 ++- src/components/node/NodeComments/index.tsx | 90 ++++++++++--------- .../node/NodeCommentsBlock/index.tsx | 26 +++++- src/constants/api.ts | 3 + src/layouts/BorisLayout/index.tsx | 3 + src/layouts/NodeLayout/index.tsx | 23 ++++- src/utils/hooks/node/useNodeComments.ts | 54 +++++++++++ src/utils/hooks/node/useNodeFetcher.ts | 2 +- 11 files changed, 184 insertions(+), 59 deletions(-) create mode 100644 src/utils/hooks/node/useNodeComments.ts diff --git a/src/components/boris/BorisComments/index.tsx b/src/components/boris/BorisComments/index.tsx index b4350c44..4a61c8d0 100644 --- a/src/components/boris/BorisComments/index.tsx +++ b/src/components/boris/BorisComments/index.tsx @@ -8,16 +8,27 @@ import { Footer } from '~/components/main/Footer'; import { Card } from '~/components/containers/Card'; import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; import { selectAuthUser } from '~/redux/auth/selectors'; -import { IComment, INode } from '~/redux/types'; +import { IComment, IFile, INode } from '~/redux/types'; interface IProps { isLoadingComments: boolean; commentCount: number; node: INode; comments: IComment[]; + onDelete: (id: IComment['id'], locked: boolean) => void; + onLoadMoreComments: () => void; + onShowPhotoswipe: (images: IFile[], index: number) => void; } -const BorisComments: FC = ({ isLoadingComments, node, commentCount, comments }) => { +const BorisComments: FC = ({ + node, + commentCount, + comments, + isLoadingComments, + onLoadMoreComments, + onDelete, + onShowPhotoswipe, +}) => { const user = useShallowSelect(selectAuthUser); return ( @@ -28,7 +39,15 @@ const BorisComments: FC = ({ isLoadingComments, node, commentCount, comm {isLoadingComments ? ( ) : ( - + )} diff --git a/src/components/comment/Comment/index.tsx b/src/components/comment/Comment/index.tsx index 6ee92c31..941c5d40 100644 --- a/src/components/comment/Comment/index.tsx +++ b/src/components/comment/Comment/index.tsx @@ -1,6 +1,6 @@ import React, { FC, HTMLAttributes, memo } from 'react'; import { CommentWrapper } from '~/components/containers/CommentWrapper'; -import { IComment, ICommentGroup } from '~/redux/types'; +import { IComment, ICommentGroup, IFile } from '~/redux/types'; import { CommentContent } from '~/components/comment/CommentContent'; import styles from './styles.module.scss'; import { CommendDeleted } from '../../node/CommendDeleted'; @@ -13,7 +13,7 @@ type IProps = HTMLAttributes & { is_same?: boolean; can_edit?: boolean; onDelete: (id: IComment['id'], isLocked: boolean) => void; - modalShowPhotoswipe: typeof MODAL_ACTIONS.modalShowPhotoswipe; + modalShowPhotoswipe: (images: IFile[], index: number) => void; }; const Comment: FC = memo( diff --git a/src/components/comment/CommentContent/index.tsx b/src/components/comment/CommentContent/index.tsx index cccdb985..8785f450 100644 --- a/src/components/comment/CommentContent/index.tsx +++ b/src/components/comment/CommentContent/index.tsx @@ -21,7 +21,7 @@ interface IProps { comment: IComment; can_edit: boolean; onDelete: (id: IComment['id'], isLocked: boolean) => void; - modalShowPhotoswipe: typeof MODAL_ACTIONS.modalShowPhotoswipe; + modalShowPhotoswipe: (images: IFile[], index: number) => void; } const CommentContent: FC = memo(({ comment, can_edit, onDelete, modalShowPhotoswipe }) => { diff --git a/src/components/node/NodeBottomBlock/index.tsx b/src/components/node/NodeBottomBlock/index.tsx index 087b5829..7e3c6b78 100644 --- a/src/components/node/NodeBottomBlock/index.tsx +++ b/src/components/node/NodeBottomBlock/index.tsx @@ -6,7 +6,7 @@ import { NodeCommentsBlock } from '~/components/node/NodeCommentsBlock'; import { NodeCommentForm } from '~/components/node/NodeCommentForm'; import { NodeRelatedBlock } from '~/components/node/NodeRelatedBlock'; import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; -import { IComment, INode } from '~/redux/types'; +import { IComment, IFile, INode } from '~/redux/types'; import { useUser } from '~/utils/hooks/user/userUser'; import { NodeTagsBlock } from '~/components/node/NodeTagsBlock'; import { INodeRelated } from '~/redux/node/types'; @@ -21,6 +21,9 @@ interface IProps { commentsCount: number; isLoadingComments: boolean; related: INodeRelated; + onDeleteComment: (id: IComment['id'], locked: boolean) => void; + onLoadMoreComments: () => void; + onShowPhotoswipe: (images: IFile[], index: number) => void; } const NodeBottomBlock: FC = ({ @@ -31,6 +34,9 @@ const NodeBottomBlock: FC = ({ commentsCount, commentsOrder, related, + onDeleteComment, + onLoadMoreComments, + onShowPhotoswipe, }) => { const { inline } = useNodeBlocks(node, isLoading); const { is_user } = useUser(); @@ -53,6 +59,9 @@ const NodeBottomBlock: FC = ({ count={commentsCount} order={commentsOrder} node={node} + onDelete={onDeleteComment} + onLoadMoreComments={onLoadMoreComments} + onShowPhotoswipe={onShowPhotoswipe} /> {is_user && !isLoading && } diff --git a/src/components/node/NodeComments/index.tsx b/src/components/node/NodeComments/index.tsx index 075c68a8..04cb1310 100644 --- a/src/components/node/NodeComments/index.tsx +++ b/src/components/node/NodeComments/index.tsx @@ -18,56 +18,58 @@ interface IProps { count: INodeState['comment_count']; user: IUser; order?: 'ASC' | 'DESC'; + onDelete: (id: IComment['id'], locked: boolean) => void; + onLoadMoreComments: () => void; + onShowPhotoswipe: (images: IFile[], index: number) => void; } -const NodeComments: FC = memo(({ comments, user, count = 0, order = 'DESC' }) => { - const dispatch = useDispatch(); - const left = useMemo(() => Math.max(0, count - comments.length), [comments, count]); +const NodeComments: FC = memo( + ({ + onLoadMoreComments, + onDelete, + onShowPhotoswipe, + comments, + user, + count = 0, + order = 'DESC', + }) => { + const left = useMemo(() => Math.max(0, count - comments.length), [comments, count]); - const groupped: ICommentGroup[] = useMemo( - () => (order === 'DESC' ? [...comments].reverse() : comments).reduce(groupCommentsByUser, []), - [comments, order] - ); + const groupped: ICommentGroup[] = useMemo( + () => (order === 'DESC' ? [...comments].reverse() : comments).reduce(groupCommentsByUser, []), + [comments, order] + ); - const onDelete = useCallback( - (id: IComment['id'], locked: boolean) => dispatch(nodeLockComment(id, locked)), - [dispatch] - ); - const onLoadMoreComments = useCallback(() => dispatch(nodeLoadMoreComments()), [dispatch]); - const onShowPhotoswipe = useCallback( - (images: IFile[], index: number) => dispatch(modalShowPhotoswipe(images, index)), - [dispatch] - ); + const more = useMemo( + () => + left > 0 && ( +
+ Показать ещё{' '} + {plural(Math.min(left, COMMENTS_DISPLAY), 'комментарий', 'комментария', 'комментариев')} + {left > COMMENTS_DISPLAY ? ` из ${left} оставшихся` : ''} +
+ ), + [left, onLoadMoreComments] + ); - const more = useMemo( - () => - left > 0 && ( -
- Показать ещё{' '} - {plural(Math.min(left, COMMENTS_DISPLAY), 'комментарий', 'комментария', 'комментариев')} - {left > COMMENTS_DISPLAY ? ` из ${left} оставшихся` : ''} -
- ), - [left, onLoadMoreComments] - ); + return ( +
+ {order === 'DESC' && more} - return ( -
- {order === 'DESC' && more} + {groupped.map(group => ( + + ))} - {groupped.map(group => ( - - ))} - - {order === 'ASC' && more} -
- ); -}); + {order === 'ASC' && more} +
+ ); + } +); export { NodeComments }; diff --git a/src/components/node/NodeCommentsBlock/index.tsx b/src/components/node/NodeCommentsBlock/index.tsx index aeab8eb2..f873eb05 100644 --- a/src/components/node/NodeCommentsBlock/index.tsx +++ b/src/components/node/NodeCommentsBlock/index.tsx @@ -1,7 +1,7 @@ import React, { FC } from 'react'; import { NodeNoComments } from '~/components/node/NodeNoComments'; import { NodeComments } from '~/components/node/NodeComments'; -import { IComment, INode } from '~/redux/types'; +import { IComment, IFile, INode } from '~/redux/types'; import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; import { useUser } from '~/utils/hooks/user/userUser'; @@ -12,16 +12,36 @@ interface IProps { count: number; isLoading: boolean; isLoadingComments: boolean; + onDelete: (id: IComment['id'], locked: boolean) => void; + onLoadMoreComments: () => void; + onShowPhotoswipe: (images: IFile[], index: number) => void; } -const NodeCommentsBlock: FC = ({ isLoading, isLoadingComments, node, comments, count }) => { +const NodeCommentsBlock: FC = ({ + onLoadMoreComments, + onDelete, + onShowPhotoswipe, + isLoading, + isLoadingComments, + node, + comments, + count, +}) => { const user = useUser(); const { inline } = useNodeBlocks(node, isLoading); return isLoading || isLoadingComments || (!comments.length && !inline) ? ( ) : ( - + ); }; diff --git a/src/constants/api.ts b/src/constants/api.ts index f834633c..becc08f1 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -1,5 +1,6 @@ import { IComment, INode } from '~/redux/types'; import { ISocialProvider } from '~/redux/auth/types'; +import { COMMENTS_DISPLAY } from '~/redux/node/constants'; export const API = { BASE: process.env.REACT_APP_API_HOST, @@ -28,6 +29,8 @@ export const API = { GET_NODE: (id: number | string) => `/node/${id}`, COMMENT: (id: INode['id']) => `/node/${id}/comment`, + COMMENT_INFINITE: (id: INode['id'], skip: number) => + `/node/${id}/comment?take=${COMMENTS_DISPLAY}&skip=${skip}`, RELATED: (id: INode['id']) => `/node/${id}/related`, UPDATE_TAGS: (id: INode['id']) => `/node/${id}/tags`, POST_LIKE: (id: INode['id']) => `/node/${id}/like`, diff --git a/src/layouts/BorisLayout/index.tsx b/src/layouts/BorisLayout/index.tsx index e5f79cfe..5816cc3f 100644 --- a/src/layouts/BorisLayout/index.tsx +++ b/src/layouts/BorisLayout/index.tsx @@ -115,6 +115,9 @@ const BorisLayout: FC = () => { commentCount={node.comment_count} node={node.current} comments={node.comments} + onDelete={console.log} + onLoadMoreComments={console.log} + onShowPhotoswipe={console.log} /> } diff --git a/src/layouts/NodeLayout/index.tsx b/src/layouts/NodeLayout/index.tsx index f14cb3f9..31426a76 100644 --- a/src/layouts/NodeLayout/index.tsx +++ b/src/layouts/NodeLayout/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, memo } from 'react'; +import React, { FC, memo, useCallback } from 'react'; import { Route, RouteComponentProps } from 'react-router'; import { selectNode } from '~/redux/node/selectors'; import { Card } from '~/components/containers/Card'; @@ -20,6 +20,10 @@ import { useOnNodeSeen } from '~/utils/hooks/node/useOnNodeSeen'; import styles from './styles.module.scss'; import { useNodeFetcher } from '~/utils/hooks/node/useNodeFetcher'; +import { useNodeComments } from '~/utils/hooks/node/useNodeComments'; +import { IFile } from '~/redux/types'; +import { modalShowPhotoswipe } from '~/redux/modal/actions'; +import { useDispatch } from 'react-redux'; type IProps = RouteComponentProps<{ id: string }> & {}; @@ -30,8 +34,16 @@ const NodeLayout: FC = memo( }, }) => { const { node, isLoading } = useNodeFetcher(parseInt(id, 10)); + const { + comments, + isLoading: isLoadingComments, + count: commentsCount, + onDelete, + onLoadMoreComments, + onShowPhotoswipe, + } = useNodeComments(parseInt(id, 10)); - const { comments, comment_count, is_loading_comments, related } = useShallowSelect(selectNode); + const { related } = useShallowSelect(selectNode); useNodeCoverImage(node); useScrollToTop([id]); @@ -52,12 +64,15 @@ const NodeLayout: FC = memo(