Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] feat: useSuspendedQuery, useSuspendedInfiniteQuery 추가 #443

Merged
merged 17 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ module.exports = {
'import/no-unresolved': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-types': 'off',
'import/export': 'off',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘는 뭐하는 친구죠??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수 오버로딩을 사용하려면 같은 이름의 함수를 여러개 선언해야하는데 린트 에러가 나서 껐습니다 ㅎㅎ...

},
settings: {
'import/resolver': {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Common/CategoryMenu/CategoryMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ interface CategoryMenuProps {
}

const CategoryMenu = ({ menuVariant }: CategoryMenuProps) => {
const { data: categoryList } = useCategoryQuery(menuVariant);
const { data: categories } = useCategoryQuery(menuVariant);
const { categoryIds, selectCategory } = useCategoryContext();

const currentCategoryId = categoryIds[menuVariant];

return (
<CategoryMenuContainer>
{categoryList?.map((menu) => {
{categories.map((menu) => {
const isSelected = menu.id === currentCategoryId;
return (
<li key={menu.id}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ const MemberReviewList = ({ isMemberPage = false }: MemberReviewListProps) => {
const scrollRef = useRef<HTMLDivElement>(null);

const { fetchNextPage, hasNextPage, data } = useInfiniteMemberReviewQuery();
const memberReviews = data?.pages.flatMap((page) => page.reviews);
const memberReviews = data.pages.flatMap((page) => page.reviews);
const reviewsToDisplay = useDisplaySlice(isMemberPage, memberReviews);

useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

const totalReviewCount = data?.pages.flatMap((page) => page.page.totalDataCount);
const totalReviewCount = data.pages.flatMap((page) => page.page.totalDataCount);

return (
<MemberReviewListContainer>
Expand All @@ -31,7 +31,7 @@ const MemberReviewList = ({ isMemberPage = false }: MemberReviewListProps) => {
)}
<Spacing size={20} />
<MemberReviewListWrapper>
{reviewsToDisplay?.map((reviewRanking) => (
{reviewsToDisplay.map((reviewRanking) => (
<li key={reviewRanking.reviewId}>
<ReviewRankingItem reviewRanking={reviewRanking} />
</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ const PBProductList = ({ isHomePage }: PBProductListProps) => {
const { categoryIds } = useCategoryContext();

const { data: pbProductListResponse } = useInfiniteProductsQuery(categoryIds.store);
const pbProductList = pbProductListResponse?.pages.flatMap((page) => page.products);
const pbProductsToDisplay = displaySlice(isHomePage, pbProductList, 10);
const pbProducts = pbProductListResponse.pages.flatMap((page) => page.products);
const pbProductsToDisplay = displaySlice(isHomePage, pbProducts, 10);

return (
<>
<PBProductListContainer>
{pbProductsToDisplay?.map((pbProduct) => (
{pbProductsToDisplay.map((pbProduct) => (
<li key={pbProduct.id}>
<Link as={RouterLink} to={`${PATH.PRODUCT_LIST}/store/${pbProduct.id}`}>
<PBProductItem pbProduct={pbProduct} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,11 @@ interface ProductDetailItemProps {
}

const ProductDetailItem = ({ productId }: ProductDetailItemProps) => {
const theme = useTheme();

const { data: productDetail } = useProductDetailQuery(productId);

if (!productDetail) {
return null;
}

const { name, price, image, content, averageRating, tags, bookmark } = productDetail;

const theme = useTheme();

return (
<>
<SectionTitle name={name} bookmark={bookmark} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styled from 'styled-components';
import PreviewImage from '@/assets/characters.svg';
import { SvgIcon } from '@/components/Common';
import type { Product } from '@/types/product';

interface ProductItemProps {
product: Product;
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Product/ProductList/ProductList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ const ProductList = ({ category, isHomePage, selectedOption }: ProductListProps)
categoryIds[category],
selectedOption?.value ?? 'reviewCount,desc'
);
const productList = data?.pages.flatMap((page) => page.products);
const productList = data.pages.flatMap((page) => page.products);
const productsToDisplay = displaySlice(isHomePage, productList);

useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

return (
<>
<ProductListContainer>
{productsToDisplay?.map((product) => (
{productsToDisplay.map((product) => (
<li key={product.id}>
<Link as={RouterLink} to={`${PATH.PRODUCT_LIST}/${category}/${product.id}`}>
<ProductItem product={product} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import styled from 'styled-components';
import PreviewImage from '@/assets/characters.svg';

interface ProductOverviewItemProps {
name: string;
image: string | null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

억지로 구겨넣은 '?'가 다 사라졌군요 👍

rank?: number;
name?: string;
image?: string;
}

const ProductOverviewItem = ({ rank, name, image }: ProductOverviewItemProps) => {
const ProductOverviewItem = ({ name, image, rank }: ProductOverviewItemProps) => {
return (
<ProductOverviewContainer rank={rank} tabIndex={0}>
<Text size="lg" weight="bold" align="center">
{rank ?? ''}
</Text>
{image ? (
{image !== null ? (
<ProductOverviewImage src={image} alt={rank ? `${rank}위 상품` : `${name}사진`} />
) : (
<ProductPreviewImage width={45} height={45} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import { ProductOverviewItem } from '@/components/Product';
import { PATH } from '@/constants/path';
import { useProductRankingQuery } from '@/hooks/queries/rank';
import displaySlice from '@/utils/displaySlice';

interface ProductRankingListProps {
isHomePage?: boolean;
}

const ProductRankingList = ({ isHomePage }: ProductRankingListProps) => {
const ProductRankingList = ({ isHomePage = false }: ProductRankingListProps) => {
const { data: productRankings } = useProductRankingQuery();
const productsToDisplay = displaySlice(isHomePage, productRankings?.products, 3);
const productsToDisplay = displaySlice(isHomePage, productRankings.products, 3);

return (
<ul>
{productsToDisplay?.map(({ id, name, image, categoryType }, index) => (
{productsToDisplay.map(({ id, name, image, categoryType }, index) => (
<li key={id}>
<Link as={RouterLink} to={`${PATH.PRODUCT_LIST}/${categoryType}/${id}`}>
<ProductOverviewItem rank={index + 1} name={name} image={image} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ interface ReviewRankingListProps {
isHomePage?: boolean;
}

const ReviewRankingList = ({ isHomePage }: ReviewRankingListProps) => {
const ReviewRankingList = ({ isHomePage = false }: ReviewRankingListProps) => {
const { data: reviewRankings } = useReviewRankingQuery();
const reviewsToDisplay = useDisplaySlice(isHomePage, reviewRankings?.reviews);
const reviewsToDisplay = useDisplaySlice(isHomePage, reviewRankings.reviews);

return (
<ReviewRankingListContainer>
{reviewsToDisplay?.map((reviewRanking) => (
{reviewsToDisplay.map((reviewRanking) => (
<li key={reviewRanking.reviewId}>
<ReviewRankingItem reviewRanking={reviewRanking} />
</li>
Expand Down
4 changes: 0 additions & 4 deletions frontend/src/components/Recipe/RecipeList/RecipeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ const RecipeList = ({ selectedOption }: RecipeListProps) => {
const { fetchNextPage, hasNextPage, data } = useInfiniteRecipesQuery(selectedOption.value);
useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

if (!data) {
return null;
}

const recipes = data.pages.flatMap((page) => page.recipes);

return (
Expand Down
71 changes: 26 additions & 45 deletions frontend/src/components/Review/ReviewList/ReviewList.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,53 @@
import { Text, Link } from '@fun-eat/design-system';
import { useRef } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';

import ReviewItem from '../ReviewItem/ReviewItem';

import { PATH } from '@/constants/path';
import { Loading } from '@/components/Common';
import { useIntersectionObserver } from '@/hooks/common';
import { useInfiniteProductReviewsQuery } from '@/hooks/queries/product';
import type { SortOption } from '@/types/common';

const LOGIN_ERROR_MESSAGE =
'로그인 해야 상품 리뷰를 볼 수 있어요.\n펀잇에 가입하고 편의점 상품의 리뷰를 확인해보세요 😊';

interface ReviewListProps {
productId: number;
selectedOption: SortOption;
}

const ReviewList = ({ productId, selectedOption }: ReviewListProps) => {
const { fetchNextPage, hasNextPage, data, isFetchingNextPage } = useInfiniteProductReviewsQuery(
productId,
selectedOption.value
);
const scrollRef = useRef<HTMLDivElement>(null);

const { fetchNextPage, hasNextPage, data, isError } = useInfiniteProductReviewsQuery(productId, selectedOption.value);
useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

if (isError) {
return (
<ErrorContainer>
<ErrorDescription align="center" weight="bold" size="lg">
{LOGIN_ERROR_MESSAGE}
</ErrorDescription>
<LoginLink as={RouterLink} to={PATH.LOGIN} block>
로그인하러 가기
</LoginLink>
</ErrorContainer>
);
}
const reviews = data.pages.flatMap((page) => page.reviews);

// TODO: 로그인 에러 페이지로 이동 예정. 다른 브랜치에서 작업중
//if (isError) {
// return (
// <ErrorContainer>
// <ErrorDescription align="center" weight="bold" size="lg">
// {LOGIN_ERROR_MESSAGE}
// </ErrorDescription>
// <LoginLink as={RouterLink} to={PATH.LOGIN} block>
// 로그인하러 가기
// </LoginLink>
// </ErrorContainer>
// );
//}

return (
<>
<ReviewListContainer>
{data?.pages
.flatMap((page) => page.reviews)
.map((review) => (
<li key={review.id}>
<ReviewItem productId={productId} review={review} />
</li>
))}
{reviews.map((review) => (
<li key={review.id}>
<ReviewItem productId={productId} review={review} />
</li>
))}
</ReviewListContainer>
<div ref={scrollRef} aria-hidden />
{isFetchingNextPage && <Loading />}
</>
);
};
Expand All @@ -60,21 +59,3 @@ const ReviewListContainer = styled.ul`
flex-direction: column;
row-gap: 60px;
`;

const ErrorContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`;

const ErrorDescription = styled(Text)`
padding: 40px 0;
white-space: pre-line;
word-break: break-all;
`;

const LoginLink = styled(Link)`
padding: 16px 24px;
border: 1px solid ${({ theme }) => theme.colors.gray4};
border-radius: 8px;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog }: ReviewR
</CloseButton>
<Divider />
<ProductOverviewItemWrapper>
<ProductOverviewItem name={productDetail?.name} image={productDetail?.image} />
<ProductOverviewItem name={productDetail.name} image={productDetail.image} />
</ProductOverviewItemWrapper>
<Divider customHeight="4px" variant="disabled" />
<RegisterForm onSubmit={handleSubmit}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ interface ReviewTagListProps {

const ReviewTagList = ({ selectedTags }: ReviewTagListProps) => {
const { data: tagsData } = useReviewTagsQuery();
const { minDisplayedTags, canShowMore, showMoreTags } = useDisplayTag(tagsData ?? [], MIN_DISPLAYED_TAGS_LENGTH);

if (!tagsData) {
return null;
}
const { minDisplayedTags, canShowMore, showMoreTags } = useDisplayTag(tagsData, MIN_DISPLAYED_TAGS_LENGTH);

return (
<ReviewTagListContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ const RecommendList = ({ searchQuery }: RecommendListProps) => {
const scrollRef = useRef<HTMLDivElement>(null);
useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

if (!searchResponse) {
return null;
}

const products = searchResponse.pages.flatMap((page) => page.products);

if (products.length === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ const SearchResultList = ({ searchQuery }: SearchResultListProps) => {
const scrollRef = useRef<HTMLDivElement>(null);
useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

if (!searchResponse) {
return null;
}

const products = searchResponse.pages.flatMap((page) => page.products);

if (products.length === 0) {
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/hooks/queries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './useSuspendedQuery';
export * from './useSuspendedInfiniteQuery';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { useSuspendedInfiniteQuery } from '..';

import { memberApi } from '@/apis';
import type { MemberReviewResponse } from '@/types/response';
Expand All @@ -10,9 +10,7 @@ const fetchMemberReview = async (pageParam: number) => {
};

const useInfiniteMemberReviewQuery = () => {
return useInfiniteQuery({
queryKey: ['member', 'reviews'],
queryFn: ({ pageParam = 0 }) => fetchMemberReview(pageParam),
return useSuspendedInfiniteQuery(['member', 'reviews'], ({ pageParam = 0 }) => fetchMemberReview(pageParam), {
getNextPageParam: (prevResponse: MemberReviewResponse) => {
const isLast = prevResponse.page.lastPage;
const nextPage = prevResponse.page.requestPage + 1;
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/hooks/queries/product/useCategoryQuery.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspendedQuery } from '..';

import { categoryApi } from '@/apis';
import type { Category } from '@/types/common';
Expand All @@ -10,10 +10,7 @@ const fetchCategories = async (type: string) => {
};

const useCategoryQuery = (type: string) => {
return useQuery({
queryKey: ['categories', type],
queryFn: () => fetchCategories(type),
});
return useSuspendedQuery(['categories', type], () => fetchCategories(type));
};

export default useCategoryQuery;
Loading
Loading