import Link from 'next/link'; import { FC, MutableRefObject, useRef } from 'react'; import { useInView } from 'react-intersection-observer'; import { z } from 'zod'; import useBeerRecommendations from '@/hooks/data-fetching/beer-posts/useBeerRecommendations'; import BeerPostQueryResult from '@/services/posts/beer-post/schema/BeerPostQueryResult'; import debounce from 'lodash/debounce'; import BeerRecommendationLoadingComponent from './BeerRecommendationLoadingComponent'; const BeerRecommendationsSection: FC<{ beerPost: z.infer; }> = ({ beerPost }) => { const PAGE_SIZE = 10; const { beerPosts, isAtEnd, isLoadingMore, setSize, size } = useBeerRecommendations({ beerPost, pageSize: PAGE_SIZE, }); const { ref: penultimateBeerPostRef } = useInView({ /** * When the last beer post comes into view, call setSize from useBeerPostsByBrewery to * load more beer posts. */ onChange: (visible) => { if (!visible || isAtEnd) return; debounce(() => setSize(size + 1), 200)(); }, }); const beerRecommendationsRef: MutableRefObject = useRef(null); return (
<>

Also check out

{!!beerPosts.length && (
{beerPosts.map((post, index) => { const isPenultimateBeerPost = index === beerPosts.length - 2; /** * Attach a ref to the second last beer post in the list. When it comes * into view, the component will call setSize to load more beer posts. */ return (
{post.name} {post.brewery.name}
{post.style.name}
{post.abv.toFixed(1)}% ABV {post.ibu.toFixed(1)} IBU
); })}
)} { /** * If there are more beer posts to load, show a loading component with a * skeleton loader and a loading spinner. */ !!isLoadingMore && !isAtEnd && ( ) }
); }; export default BeerRecommendationsSection;