Skip to content

Commit

Permalink
refactor: search 페이지 코드 개선 (#162)
Browse files Browse the repository at this point in the history
* refactor: search FallbackComponent 추상화 작업

* refactor: ResultListItems -> ResultList 컴포넌트명 변경

* refactor: useScrollObserve hook 분리

* chore: ppussungError svg 추가

* feat: 서버에러 FallbackComponent 제작

* fix: 불필요한 코드 삭제

* fix: StyledTextContainer 스타일 속성 추가

* refactor: 검색 결과 없음 customErrorcode으로 리팩토링

* refactor: navigation_options 상수화

* refactor: 무한스크롤 코드 리팩토링

* refactor: suspense TotalCount 컴포넌트 내부로 이동

* refactor: YDS 제거 및 StyledBoxButton 추가

* fix: navigate(0) -> navigate(-1)

* fix: ResultListItem -> ResultList 폴더명 수정

* refactor: customError 함수형으로 수정 및 네이밍 수정

* fix: 이름 속성값 고정 -> 인자로 받는 것으로 변경

* fix: FallbackComponent -> ErrorFallback rename

* feat: NoResultFallback 컴포넌트 제작

* fix: 숨실 -> 숨쉴 오타 수정

* refactor: error 처리 방식 -> NoResultFallback 처리 방식 수정

* fix: 불필요한 코드 삭제

* fix: 불필요한 코드 삭제
  • Loading branch information
intersoom authored May 19, 2024
1 parent c5c664e commit 69b5624
Show file tree
Hide file tree
Showing 17 changed files with 265 additions and 105 deletions.
3 changes: 0 additions & 3 deletions src/search/apis/getSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export const getSearch = async ({ query, page }: GetSearchProps) => {
},
})
.then((response) => {
if (response.data.totalCount === 0) {
throw new Error('검색결과가 없습니다.');
}
return response;
});

Expand Down
20 changes: 20 additions & 0 deletions src/search/assets/ppussungError.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions src/search/components/FallbackComponent/ErrorFallback.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import styled from 'styled-components';

export const StyledContainer = styled.div`
display: flex;
width: auto;
height: 168px;
flex-direction: row;
justify-content: space-between;
gap: 2rem;
flex-shrink: 0;
`;

export const StyledTextButtonContainer = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
`;

export const StyledTextContainer = styled.div`
width: fit-content;
display: flex;
flex-direction: column;
`;

export const StyledButtonContainer = styled.div`
display: flex;
gap: 0.75rem;
`;

interface StyledBoxButtonProps {
variant: 'line' | 'filled';
}

export const StyledBoxButton = styled.button<StyledBoxButtonProps>`
${(props) => props.theme.typo.button0};
color: ${(props) => (props.variant === 'filled' ? '#FFF' : '#5865f2')};
width: 8.375rem;
height: 3rem;
border-radius: 0.375rem;
border: 1px solid var(--logoLightBlue, #5865f2);
background: ${(props) =>
props.variant === 'filled' ? 'var(--logoLightBlue, #5865f2)' : 'transparent'};
`;

export const StyledBoldText = styled.text`
display: block;
color: ${(props) => props.theme.color.textPrimary};
${(props) => props.theme.typo.subtitle2};
`;

export const StyledSubText = styled.text`
display: block;
color: ${(props) => props.theme.color.textTertiary};
${(props) => props.theme.typo.body3};
`;

export const StyledErrorImg = styled.img`
width: 8.81375rem;
`;
57 changes: 57 additions & 0 deletions src/search/components/FallbackComponent/ErrorFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { FallbackProps } from 'react-error-boundary';
import { useNavigate } from 'react-router-dom';

import { Spacing } from '@/components/Spacing/Spacing';
import ppussungError from '@/search/assets/ppussungError.svg';
import { NAVIGATION_OPTIONS } from '@/search/constant';

import {
StyledBoldText,
StyledContainer,
StyledSubText,
StyledTextButtonContainer,
StyledTextContainer,
StyledButtonContainer,
StyledBoxButton,
} from './ErrorFallback.style';

export const ErrorFallback = ({ resetErrorBoundary }: FallbackProps) => {
const navigate = useNavigate();

const handleClick = (option: keyof typeof NAVIGATION_OPTIONS) => {
resetErrorBoundary();

switch (option) {
case 'HOME':
navigate('/');
break;
case 'PREVIOUS':
navigate(-1);
break;
default:
}
};

return (
<StyledContainer>
<StyledTextButtonContainer>
<StyledTextContainer>
<StyledBoldText>시스템 오류가 발생했습니다!</StyledBoldText>
<Spacing direction="vertical" size={12} />
<StyledSubText>
오류로 인하여 페이지를 표시할 수 없습니다. 이용에 불편을 드려 죄송합니다.
</StyledSubText>
</StyledTextContainer>
<StyledButtonContainer>
<StyledBoxButton variant="line" onClick={() => handleClick('HOME')}>
숨쉴 홈으로
</StyledBoxButton>
<StyledBoxButton variant="filled" onClick={() => handleClick('PREVIOUS')}>
이전 페이지
</StyledBoxButton>
</StyledButtonContainer>
</StyledTextButtonContainer>
<img src={ppussungError} alt="error" />
</StyledContainer>
);
};
20 changes: 0 additions & 20 deletions src/search/components/FallbackComponent/FallbackComponent.tsx

This file was deleted.

15 changes: 15 additions & 0 deletions src/search/components/FallbackComponent/NoResultFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ReactNode } from 'react';

import { ResultListItemResponse } from '@/search/types/ResultListItem.type';

interface NoResultFallbackFallbackProps {
results: ResultListItemResponse[];
fallback: ReactNode;
children: ReactNode;
}

const NoResultFallback = ({ results, fallback, children }: NoResultFallbackFallbackProps) => {
return results.length > 0 ? children : fallback;
};

export default NoResultFallback;
42 changes: 42 additions & 0 deletions src/search/components/ResultList/ResultList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Suspense } from 'react';

import { useSearchParams } from 'react-router-dom';

import { Loading } from '@/components/Loading/Loading';
import { Spacing } from '@/components/Spacing/Spacing';
import { useGetSearch } from '@/search/hooks/useGetSearch';
import { useScrollObserve } from '@/search/hooks/useScrollObserve';
import { NoResult } from '@/search/pages/NoResult/NoResult';

import NoResultFallback from '../FallbackComponent/NoResultFallback';

import { ResultListItem } from './ResultListItem';

export const ResultList = () => {
const [searchParams] = useSearchParams();
const query = searchParams.get('query');

const { data, isPending, fetchNextPage, hasNextPage } = useGetSearch({
query: query || '',
});

const { lastElementRef } = useScrollObserve({ isPending, fetchNextPage, hasNextPage });

return (
<NoResultFallback results={data?.pages[0].resultList} fallback={<NoResult />}>
<Suspense fallback={<Loading />}>
{data?.pages.map((page) => {
return page.resultList.map((item, itemIndex) => {
const isLastItem = page.resultList.length === itemIndex + 1;
return (
<div key={item.id}>
<ResultListItem {...item} ref={isLastItem ? lastElementRef : null}></ResultListItem>
<Spacing direction="vertical" size={8} />
</div>
);
});
})}
</Suspense>
</NoResultFallback>
);
};
57 changes: 0 additions & 57 deletions src/search/components/ResultListItem/ResultListItems.tsx

This file was deleted.

14 changes: 13 additions & 1 deletion src/search/components/TotalCount/TotalCount.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Suspense } from 'react';

import { useSearchParams } from 'react-router-dom';

import { Spacing } from '@/components/Spacing/Spacing';
import { useGetSearch } from '@/search/hooks/useGetSearch';
import { StyledTotalCount } from '@/search/pages/Search/Search.style';

import NoResultFallback from '../FallbackComponent/NoResultFallback';

export const TotalCount = () => {
const [searchParams] = useSearchParams();
const query = searchParams.get('query') ?? '';
Expand All @@ -12,6 +17,13 @@ export const TotalCount = () => {
});

return (
<StyledTotalCount>{`${data.pages[0].totalCount}개의 검색 결과가 있습니다`}</StyledTotalCount>
<NoResultFallback
results={data?.pages[0].resultList}
fallback={<Spacing direction="vertical" size={21} />}
>
<Suspense fallback={<Spacing direction="vertical" size={21} />}>
<StyledTotalCount>{`${data.pages[0].totalCount}개의 검색 결과가 있습니다`}</StyledTotalCount>
</Suspense>
</NoResultFallback>
);
};
3 changes: 3 additions & 0 deletions src/search/constant/customError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const CustomErrorCode = {
NoResult: 1000,
};
5 changes: 5 additions & 0 deletions src/search/constant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ export const SEARCH_BOX_RADIAL_GRADIENT: Record<string, Record<SearchSize, strin
};

export const RESULT_LIST_ITEM_THUMNAIL_LENGTH = 5;

export const NAVIGATION_OPTIONS = {
HOME: 'home',
PREVIOUS: 'previous',
};
6 changes: 1 addition & 5 deletions src/search/hooks/useGetSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ export const useGetSearch = ({ query }: GetSearchProps) => {

return allPages.length;
},
retryDelay: (_, error) => {
if (error.message === '검색결과가 없습니다.') {
return 0;
}

retryDelay: () => {
return 1000;
},
staleTime: 1000 * 60 * 5,
Expand Down
42 changes: 42 additions & 0 deletions src/search/hooks/useScrollObserve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useCallback, useRef } from 'react';

import {
FetchNextPageOptions,
InfiniteData,
InfiniteQueryObserverResult,
} from '@tanstack/react-query';

import { SearchResponse } from '../types/ResultListItem.type';

interface useScrollObserveParams {
isPending: boolean;
hasNextPage: boolean;
fetchNextPage: (
options?: FetchNextPageOptions
) => Promise<InfiniteQueryObserverResult<InfiniteData<SearchResponse, unknown>, Error>>;
}

export const useScrollObserve = ({
isPending,
hasNextPage,
fetchNextPage,
}: useScrollObserveParams) => {
const observer = useRef<IntersectionObserver>();

const lastElementRef = useCallback(
(node: HTMLDivElement) => {
if (isPending) return;

if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasNextPage) {
fetchNextPage();
}
});
if (node) observer.current.observe(node);
},
[isPending, hasNextPage, fetchNextPage]
);

return { lastElementRef };
};
2 changes: 1 addition & 1 deletion src/search/pages/NoResult/NoResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const ADD_SECTION_DATA: AddSectionData[] = [
},
{
linkText: '숨쉴위키에서 편집하기',
linkTextDescription: '이미 알고 있는 내용이라면 숨실위키에 내용을 추가해주세요',
linkTextDescription: '이미 알고 있는 내용이라면 숨쉴위키에 내용을 추가해주세요',
href: `https://wiki.soomsil.de/wiki/index.php?title={query}&action=edit`,
},
];
Expand Down
Loading

0 comments on commit 69b5624

Please sign in to comment.