import { FC, MutableRefObject } from 'react'; import { FaArrowUp } from 'react-icons/fa'; import { mutate } from 'swr'; import { useInView } from 'react-intersection-observer'; import useBeerPostComments from '@/hooks/useBeerPostComments'; import useBreweryPostComments from '@/hooks/useBreweryPostComments'; import NoCommentsCard from '../BeerById/NoCommentsCard'; import LoadingComponent from '../BeerById/LoadingComponent'; import CommentCardBody from '../BeerById/CommentCardBody'; interface CommentsComponentProps { commentSectionRef: MutableRefObject; pageSize: number; size: ReturnType['size']; setSize: ReturnType< typeof useBeerPostComments | typeof useBreweryPostComments >['setSize']; comments: ReturnType< typeof useBeerPostComments | typeof useBreweryPostComments >['comments']; isAtEnd: ReturnType< typeof useBeerPostComments | typeof useBreweryPostComments >['isAtEnd']; isLoadingMore: ReturnType< typeof useBeerPostComments | typeof useBreweryPostComments >['isLoadingMore']; } const CommentsComponent: FC = ({ commentSectionRef, comments, isAtEnd, isLoadingMore, pageSize, setSize, size, }) => { const { ref: penultimateCommentRef } = useInView({ /** * When the second last comment comes into view, call setSize from useBeerPostComments * to load more comments. */ onChange: (visible) => { if (!visible || isAtEnd) return; setSize(size + 1); }, }); return ( <> {!!comments.length && (
{comments.map((comment, index) => { const isPenultimateComment = index === comments.length - 2; /** * Attach a ref to the last comment in the list. When it comes into view, the * component will call setSize to load more comments. */ return (
); })} { /** * If there are more comments to load, show a loading component with a * skeleton loader and a loading spinner. */ !!isLoadingMore && } { /** * If the user has scrolled to the end of the comments, show a button that * will scroll them back to the top of the comments section. */ !!isAtEnd && (
) }
)} {!comments.length && } ); }; export default CommentsComponent;