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<IProps> = ({ isLoadingComments, node, commentCount, comments }) => {
+const BorisComments: FC<IProps> = ({
+  node,
+  commentCount,
+  comments,
+  isLoadingComments,
+  onLoadMoreComments,
+  onDelete,
+  onShowPhotoswipe,
+}) => {
   const user = useShallowSelect(selectAuthUser);
 
   return (
@@ -28,7 +39,15 @@ const BorisComments: FC<IProps> = ({ isLoadingComments, node, commentCount, comm
         {isLoadingComments ? (
           <NodeNoComments is_loading count={7} />
         ) : (
-          <NodeComments comments={comments} count={commentCount} user={user} order="ASC" />
+          <NodeComments
+            comments={comments}
+            count={commentCount}
+            user={user}
+            order="ASC"
+            onLoadMoreComments={onLoadMoreComments}
+            onDelete={onDelete}
+            onShowPhotoswipe={onShowPhotoswipe}
+          />
         )}
       </Group>
 
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<HTMLDivElement> & {
   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<IProps> = 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<IProps> = 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<IProps> = ({
@@ -31,6 +34,9 @@ const NodeBottomBlock: FC<IProps> = ({
   commentsCount,
   commentsOrder,
   related,
+  onDeleteComment,
+  onLoadMoreComments,
+  onShowPhotoswipe,
 }) => {
   const { inline } = useNodeBlocks(node, isLoading);
   const { is_user } = useUser();
@@ -53,6 +59,9 @@ const NodeBottomBlock: FC<IProps> = ({
               count={commentsCount}
               order={commentsOrder}
               node={node}
+              onDelete={onDeleteComment}
+              onLoadMoreComments={onLoadMoreComments}
+              onShowPhotoswipe={onShowPhotoswipe}
             />
 
             {is_user && !isLoading && <NodeCommentForm nodeId={node?.id} />}
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<IProps> = memo(({ comments, user, count = 0, order = 'DESC' }) => {
-  const dispatch = useDispatch();
-  const left = useMemo(() => Math.max(0, count - comments.length), [comments, count]);
+const NodeComments: FC<IProps> = 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 && (
+          <div className={styles.more} onClick={onLoadMoreComments}>
+            Показать ещё{' '}
+            {plural(Math.min(left, COMMENTS_DISPLAY), 'комментарий', 'комментария', 'комментариев')}
+            {left > COMMENTS_DISPLAY ? ` из ${left} оставшихся` : ''}
+          </div>
+        ),
+      [left, onLoadMoreComments]
+    );
 
-  const more = useMemo(
-    () =>
-      left > 0 && (
-        <div className={styles.more} onClick={onLoadMoreComments}>
-          Показать ещё{' '}
-          {plural(Math.min(left, COMMENTS_DISPLAY), 'комментарий', 'комментария', 'комментариев')}
-          {left > COMMENTS_DISPLAY ? ` из ${left} оставшихся` : ''}
-        </div>
-      ),
-    [left, onLoadMoreComments]
-  );
+    return (
+      <div className={styles.wrap}>
+        {order === 'DESC' && more}
 
-  return (
-    <div className={styles.wrap}>
-      {order === 'DESC' && more}
+        {groupped.map(group => (
+          <Comment
+            key={group.ids.join()}
+            comment_group={group}
+            can_edit={canEditComment(group, user)}
+            onDelete={onDelete}
+            modalShowPhotoswipe={onShowPhotoswipe}
+          />
+        ))}
 
-      {groupped.map(group => (
-        <Comment
-          key={group.ids.join()}
-          comment_group={group}
-          can_edit={canEditComment(group, user)}
-          onDelete={onDelete}
-          modalShowPhotoswipe={onShowPhotoswipe}
-        />
-      ))}
-
-      {order === 'ASC' && more}
-    </div>
-  );
-});
+        {order === 'ASC' && more}
+      </div>
+    );
+  }
+);
 
 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<IProps> = ({ isLoading, isLoadingComments, node, comments, count }) => {
+const NodeCommentsBlock: FC<IProps> = ({
+  onLoadMoreComments,
+  onDelete,
+  onShowPhotoswipe,
+  isLoading,
+  isLoadingComments,
+  node,
+  comments,
+  count,
+}) => {
   const user = useUser();
   const { inline } = useNodeBlocks(node, isLoading);
 
   return isLoading || isLoadingComments || (!comments.length && !inline) ? (
     <NodeNoComments is_loading={isLoadingComments || isLoading} />
   ) : (
-    <NodeComments count={count} comments={comments} user={user} order="DESC" />
+    <NodeComments
+      count={count}
+      comments={comments}
+      user={user}
+      order="DESC"
+      onLoadMoreComments={onLoadMoreComments}
+      onDelete={onDelete}
+      onShowPhotoswipe={onShowPhotoswipe}
+    />
   );
 };
 
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<IProps> = () => {
                   commentCount={node.comment_count}
                   node={node.current}
                   comments={node.comments}
+                  onDelete={console.log}
+                  onLoadMoreComments={console.log}
+                  onShowPhotoswipe={console.log}
                 />
               </Switch>
             }
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<IProps> = 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<IProps> = memo(
 
             <NodeBottomBlock
               node={node}
-              isLoadingComments={is_loading_comments}
               comments={comments}
               isLoading={isLoading}
-              commentsCount={comment_count}
+              isLoadingComments={isLoadingComments}
+              commentsCount={commentsCount}
               commentsOrder="DESC"
               related={related}
+              onShowPhotoswipe={onShowPhotoswipe}
+              onDeleteComment={onDelete}
+              onLoadMoreComments={onLoadMoreComments}
             />
 
             <Footer />
diff --git a/src/utils/hooks/node/useNodeComments.ts b/src/utils/hooks/node/useNodeComments.ts
new file mode 100644
index 00000000..d108ed4f
--- /dev/null
+++ b/src/utils/hooks/node/useNodeComments.ts
@@ -0,0 +1,54 @@
+import { IComment, IFile, INode } from '~/redux/types';
+import useSWRInfinite from 'swr/infinite';
+import { ApiGetNodeCommentsResponse } from '~/redux/node/api';
+import { api, cleanResult } from '~/utils/api';
+import { API } from '~/constants/api';
+import { useCallback, useMemo } from 'react';
+import { COMMENTS_DISPLAY } from '~/redux/node/constants';
+import { nodeLockComment } from '~/redux/node/actions';
+import { useDispatch } from 'react-redux';
+import { modalShowPhotoswipe } from '~/redux/modal/actions';
+
+export const fetcher = (url: string) => api.get<ApiGetNodeCommentsResponse>(url).then(cleanResult);
+
+export const useNodeComments = (id: INode['id']) => {
+  const dispatch = useDispatch();
+
+  const getKey = useCallback(
+    (pageIndex, previousPageData) => {
+      if (previousPageData && !previousPageData?.comments?.length) return null;
+      return API.NODE.COMMENT_INFINITE(id, pageIndex * COMMENTS_DISPLAY);
+    },
+    [id]
+  );
+
+  const { data, error, isValidating, size, setSize } = useSWRInfinite(getKey, fetcher);
+
+  const comments = useMemo<IComment[]>(
+    () => (data || []).reduce((acc, { comments }) => [...acc, ...comments], [] as IComment[]),
+    [data]
+  );
+
+  const count = useMemo<number>(() => {
+    if (!data) {
+      return 0;
+    }
+
+    return data[data.length - 1].comment_count || 0;
+  }, [data]);
+
+  const isLoading = !data && !isValidating;
+
+  const onDelete = useCallback(
+    (id: IComment['id'], locked: boolean) => dispatch(nodeLockComment(id, locked)),
+    [dispatch]
+  );
+  const onLoadMoreComments = useCallback(() => setSize(size + 1), [size, setSize]);
+
+  const onShowPhotoswipe = useCallback(
+    (images: IFile[], index: number) => dispatch(modalShowPhotoswipe(images, index)),
+    [dispatch]
+  );
+
+  return { comments, count, error, isLoading, onDelete, onLoadMoreComments, onShowPhotoswipe };
+};
diff --git a/src/utils/hooks/node/useNodeFetcher.ts b/src/utils/hooks/node/useNodeFetcher.ts
index 7376d8cf..5c727829 100644
--- a/src/utils/hooks/node/useNodeFetcher.ts
+++ b/src/utils/hooks/node/useNodeFetcher.ts
@@ -5,7 +5,7 @@ import { apiGetNode } from '~/redux/node/api';
 export const useNodeFetcher = (id: INode['id']) => {
   const { data, error, isValidating } = useSWR(`${id}`, apiGetNode);
   const node = data?.node;
-  const isLoading = !node && !isValidating;
+  const isLoading = !data && !isValidating;
 
   return { node, error, isLoading };
 };