Open ruehan opened 7 hours ago
커뮤니티를 기준으로 무한스크롤 예시를 만들어봤습니다. 실제 코드와 다른 부분이 있으니 참고용으로 사용하시면 좋을 듯 합니다.
// types export interface UserInfo { nickname: string; profile_image: string; } export interface Post { id: number; user_id: number; emotion_type: string; content: string; ai_content: string; created_at: string; is_shared: boolean; is_solved: boolean; like_count: number; comment_count: number; user_info: UserInfo; } export type SortOption = 'latest' | 'oldest' | 'comments' | 'likes';
// api/posts.ts import axios from 'axios'; import { Post, SortOption } from '../types/post'; const BASE_URL = 'https://calmiary-be.org'; interface FetchPostsParams { pageParam?: number; sortBy?: SortOption; } export const fetchPosts = async ({ pageParam = 1, sortBy = 'latest' }: FetchPostsParams) => { const response = await axios.get<Post[]>(`${BASE_URL}/posts`, { params: { page: pageParam, limit: 3, sort_by: sortBy, }, }); return response.data; };
// components/PostList.tsx import React from 'react'; import { useInfiniteQuery } from '@tanstack/react-query'; import { useInView } from 'react-intersection-observer'; import { Post, SortOption } from '../types/post'; import { fetchPosts } from '../api/posts'; interface PostListProps { sortBy: SortOption; } export const PostList = ({ sortBy } : PostListProps) => { // ref: 관찰할 요소에 붙일 참조 // inView: 해당 요소가 뷰포트에 보이는지 여부 const { ref, inView } = useInView(); const { data, // 페이지별 데이터를 포함하는 객체 isLoading, // 로딩 상태 isError, // 에러 발생 여부 hasNextPage, // 다음 페이지 존재 여부 fetchNextPage, // 다음 페이지 데이터를 불러오는 함수 isFetchingNextPage, // 다음 페이지 로딩 상태 } = useInfiniteQuery({ queryKey: ['posts', sortBy], // queryKey는 적절하게 변경 // 실제 데이터를 가져오는 함수 queryFn: ({ pageParam = 1 }) => fetchPosts({ pageParam, sortBy }), // 다음 페이지 파라미터를 결정하는 함수 getNextPageParam: (lastPage, allPages) => { // 마지막 페이지가 3개의 항목을 가지고 있으면 다음 페이지가 있다고 판단 가능 return lastPage.length === 3 ? allPages.length + 1 : undefined; }, // 초기 페이지 initialPageParam: 1, }); useEffect(() => { // 관찰 대상이 화면에 보이고 다음 페이지가 있다면 if (inView && hasNextPage) { fetchNextPage(); // 다음 페이지 로드 } }, [inView, hasNextPage, fetchNextPage]); if (isLoading) return <div>Loading...</div>; if (isError) return <div>Error loading posts</div>; return ( <div className="post-list"> {data.pages.map((group, i) => ( <Fragment key={i}> {group.map((post: Post) => ( <div key={post.id} className="post-card"> <h3>{post.content}</h3> <div className="post-meta"> <span>좋아요: {post.like_count}</span> <span>댓글: {post.comment_count}</span> </div> <div className="user-info"> <img src={post.user_info.profile_image} alt="Profile" /> <span>{post.user_info.nickname}</span> </div> </div> ))} </Fragment> ))} // 여기가 intersection observer에서 관찰하는 부분..! <div ref={ref} style={{ height: '20px' }}> {isFetchingNextPage && <div>Loading more...</div>} </div> </div> ); };
@zelkovaria @kod0751
useEffect 부분은 좀 더 비교해서 학습해볼게용 ㅎㅎ 감사합니당!
커뮤니티를 기준으로 무한스크롤 예시를 만들어봤습니다. 실제 코드와 다른 부분이 있으니 참고용으로 사용하시면 좋을 듯 합니다.
@zelkovaria @kod0751