Skip to content

Commit

Permalink
feat: 소식 페이지 API 및 무한 스크롤 추가 (#249)
Browse files Browse the repository at this point in the history
* feat: 소식페이지 무한스크롤을 위한 API 훅 추가

* feat: 소식 페이지 무한 스크롤 추가

* fix: eslint-disable 삭제

* fix: eslint-disable 삭제
  • Loading branch information
hjy0951 authored Aug 27, 2024
1 parent 4c8c175 commit 8cf3668
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 28 deletions.
13 changes: 13 additions & 0 deletions app/api/news/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NextRequest, NextResponse } from 'next/server';

import { fetchData } from '@/apis/fetch-data';
import { NewsResponse } from '@/features/news';

export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const cursorId = searchParams.get('cursorId');
const queryString = cursorId ? `?cursorId=${cursorId}` : '';
const data = await fetchData<NewsResponse>(`/news${queryString}`, 'GET');

return NextResponse.json(data);
}
15 changes: 8 additions & 7 deletions features/main/components/time-line/organisms/time-line.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* eslint-disable */
import { Fragment } from 'react';

import { SwimmerIcon } from '@/components/atoms';
import { InfiniteScroller } from '@/components/molecules';
import { TimeLineContent, useTimeLineData } from '@/features/main';
import { css, cx } from '@/styled-system/css';
import { flex } from '@/styled-system/patterns';
import { TimeLineCard } from '../molecules';
import { formatDateToKorean, getFormatDate } from '@/utils';
import { Fragment } from 'react';

import { CardWrapper } from '../atoms';
import { InfiniteScroller } from '@/components/molecules';
import { SwimmerIcon } from '@/components/atoms';
import { TimeLineContent, useTimeLineData } from '@/features/main';
import { TimeLineCard } from '../molecules';

interface GroupedTimelineContents {
date: string;
Expand Down Expand Up @@ -38,7 +39,7 @@ export const TimeLine = () => {
) : (
<InfiniteScroller
isLastPage={!hasNextPage}
onIntersect={() => fetchNextPage()}
onIntersect={() => void fetchNextPage()}
>
<ol className={listStyles}>
{groupedContents.map(({ date, contents }, groupIndex) => (
Expand Down
50 changes: 30 additions & 20 deletions features/news/components/organisms/news-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
import { useRef } from 'react';

import { PullToRefresh } from '@/components/atoms';
import { HeaderBar } from '@/components/molecules';
import { HeaderBar, InfiniteScroller } from '@/components/molecules';
import { TimeLineCard, TimeLineContent } from '@/features/main';
import { css } from '@/styled-system/css';
import { flex } from '@/styled-system/patterns';

import { NewsItem } from '../../types';
import { useNewsData } from '../../hooks';
import { NewsContent } from '../../types';
import { FindMemberButton, FollowingListLinkButton } from '../atoms';
import { EmptyNews, NewsItemWrapper, NewsItemWrapperProps } from '../molecules';

export const NewsList = () => {
const ptrRef = useRef(null);
const data: Array<NewsItem> = [];
const isEmpty = data.length === 0;
const lastItemIndex = data.length - 1;
const { data: newsData, fetchNextPage, hasNextPage } = useNewsData();

if (!newsData) return null;

const contents = newsData.pages.flatMap(({ data }) => data.content);
const isEmpty = contents.length === 0;
const lastItemIndex = contents.length - 1;

return isEmpty ? (
<section className={emptySectionStyle}>
Expand All @@ -38,26 +43,31 @@ export const NewsList = () => {
ref={ptrRef}
onRefresh={() => console.log('refreshing')}
/>
<ol className={listStyles}>
{data.map((content, index) => {
const { wrapperProps, cardContent } = getPropsObjects(content);
return (
<NewsItemWrapper
key={cardContent.memoryId}
{...wrapperProps}
isLast={lastItemIndex === index}
>
<TimeLineCard content={cardContent} isViewDate={false} />
</NewsItemWrapper>
);
})}
</ol>
<InfiniteScroller
isLastPage={!hasNextPage}
onIntersect={() => void fetchNextPage()}
>
<ol className={listStyles}>
{contents.map((content, index) => {
const { wrapperProps, cardContent } = getPropsObjects(content);
return (
<NewsItemWrapper
key={cardContent.memoryId}
{...wrapperProps}
isLast={lastItemIndex === index}
>
<TimeLineCard content={cardContent} isViewDate={false} />
</NewsItemWrapper>
);
})}
</ol>
</InfiniteScroller>
</div>
</>
);
};

const getPropsObjects = (content: NewsItem) => {
const getPropsObjects = (content: NewsContent) => {
const {
memberId,
memberNickName,
Expand Down
1 change: 1 addition & 0 deletions features/news/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './use-news-data';
25 changes: 25 additions & 0 deletions features/news/hooks/use-news-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useInfiniteQuery } from '@tanstack/react-query';

import { NewsResponse } from '../types';

const getNewsData = async (cursorId: unknown) => {
const queryString = cursorId ? `?cursorId=${cursorId as string}` : '';
const res = await fetch(`/api/news${queryString}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

return res.json();
};

export const useNewsData = () => {
return useInfiniteQuery<NewsResponse>({
queryKey: ['newsData'],
queryFn: ({ pageParam = undefined }) => getNewsData(pageParam),
initialPageParam: null,
getNextPageParam: (lastPage) =>
lastPage.data.hasNext ? lastPage.data.cursorId : undefined,
});
};
10 changes: 9 additions & 1 deletion features/news/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Response } from '@/apis';
import { TimeLineContent } from '@/features/main';

import { NewsItemWrapperProps } from '../components';

export type NewsItem = TimeLineContent & NewsItemWrapperProps;
export type NewsContent = TimeLineContent & NewsItemWrapperProps;

export type NewsResponse = Response<{
content: Array<NewsContent>;
pageSize: number;
cursorId: number;
hasNext: boolean;
}>;

0 comments on commit 8cf3668

Please sign in to comment.