feat: 공지사항 무한스크롤 추가
This commit is contained in:
parent
071d7d6e51
commit
f20bd2dd51
@ -0,0 +1,33 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export default function IntersectionArea({ onObserve, once = false }) {
|
||||
const ref = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const callback = (entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
onObserve();
|
||||
if (once) {
|
||||
observer.disconnect();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const observer = new IntersectionObserver(callback, {
|
||||
root: null,
|
||||
rootMargin: '0px',
|
||||
threshold: 0.5,
|
||||
});
|
||||
|
||||
if (ref.current) {
|
||||
observer.observe(ref.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, [onObserve, once]);
|
||||
|
||||
return <div ref={ref} />;
|
||||
}
|
1
frontend/src/components/IntersectionArea/index.js
Normal file
1
frontend/src/components/IntersectionArea/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default as IntersectionArea } from './IntersectionArea';
|
@ -2,3 +2,4 @@ export const API_URL = import.meta.env.VITE_API_URL;
|
||||
export const ROOM_URL = import.meta.env.VITE_ROOM_URL;
|
||||
export const CHAT_URL = import.meta.env.VITE_CHAT_URL;
|
||||
export const STATIC_URL = import.meta.env.VITE_STATIC_URL;
|
||||
export const PAGE_SIZE = 20;
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
|
||||
import instance from '../../utils/axios/instance';
|
||||
import { API_URL } from '../../constants';
|
||||
import { API_URL, PAGE_SIZE } from '../../constants';
|
||||
|
||||
export function useNotices(lectureId, page = 0) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['noticelist', lectureId, page],
|
||||
queryFn: () => instance.get(`${API_URL}/board?lectureId=${lectureId}&category=announcement&pageNo=${page}`),
|
||||
export function useNotices(lectureId) {
|
||||
return useSuspenseInfiniteQuery({
|
||||
queryKey: ['noticelist', lectureId],
|
||||
queryFn: ({ pageParam = 0 }) =>
|
||||
instance.get(`${API_URL}/board?lectureId=${lectureId}&category=announcement&pageNo=${pageParam}`),
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
if (lastPage.data.length < PAGE_SIZE) {
|
||||
return undefined;
|
||||
}
|
||||
return allPages.length + 1;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { useQnas } from '../../hooks/api/useQnas';
|
||||
export default function LearningLectureDetailPage() {
|
||||
const { lectureId } = useParams();
|
||||
const { data: noticesData } = useNotices(lectureId);
|
||||
const notices = noticesData?.data.slice(0, 3);
|
||||
const notices = noticesData.pages[0]?.data.slice(0, 3);
|
||||
const { data: qnasData } = useQnas(lectureId);
|
||||
const questions = qnasData?.data.slice(0, 3);
|
||||
|
||||
|
@ -3,11 +3,12 @@ import ArticleBoard from '../../components/ArticleBoard/ArticleBoard';
|
||||
import { useNotices } from '../../hooks/api/useNotices';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import useBoundStore from '../../store';
|
||||
import IntersectionArea from '../../components/IntersectionArea/IntersectionObserver';
|
||||
|
||||
export default function NoticeListPage() {
|
||||
const { lectureId } = useParams();
|
||||
const { data } = useNotices(lectureId);
|
||||
const notices = data?.data;
|
||||
const { data, fetchNextPage, hasNextPage } = useNotices(lectureId);
|
||||
const notices = data?.pages.flatMap((page) => page.data);
|
||||
const userType = useBoundStore((state) => state.userType);
|
||||
|
||||
return (
|
||||
@ -24,6 +25,7 @@ export default function NoticeListPage() {
|
||||
to={`${notice.id}`}
|
||||
/>
|
||||
))}
|
||||
{hasNextPage && <IntersectionArea onObserve={() => fetchNextPage()} />}
|
||||
</ArticleBoard>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user