-
Notifications
You must be signed in to change notification settings - Fork 7
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
MyTemplatePage 초기 랜더링 Layoutshift 개선 #706
Changes from 6 commits
d400bdf
d9609d8
cedc2ba
0d83344
cfb88bc
0be7178
5074e61
88b6c3f
b5215c6
d62ccac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,32 @@ | ||
import { Text } from '@/components'; | ||
import { useAuth } from '@/hooks/authentication'; | ||
|
||
import * as S from './Footer.style'; | ||
|
||
const Footer = () => ( | ||
<S.FooterContainer> | ||
<Text.Small color='inherit'> | ||
Copyright{' '} | ||
<Text.Small color='inherit' weight='bold'> | ||
Codezap | ||
</Text.Small>{' '} | ||
© All rights reserved. | ||
</Text.Small> | ||
<S.ContactEmail href='mailto:[email protected]'> | ||
<Text.Small color='inherit' weight='bold'> | ||
문의 : | ||
</Text.Small>{' '} | ||
<Text.Small color='inherit'>[email protected]</Text.Small>{' '} | ||
</S.ContactEmail> | ||
</S.FooterContainer> | ||
); | ||
const Footer = () => { | ||
const { isChecking } = useAuth(); | ||
|
||
if (isChecking) { | ||
return null; | ||
} | ||
Comment on lines
+7
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 suspense 처리만 해주어도 footer 관련 Layout Shift가 해결이 되나요?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분은 Header와 동일한 로직으로 변경한 것인데요, 로그인한 유저인지 아닌지 검사하는동안 footer를 null 로 처리했다가 나중에 return 해주었습니다. 이렇게 하면 Layout Shift을 완벽하게 해결할 순 없지만 처음에 너무 빨리 렌더링 되는 것을 막아 깜빡이는 현상을 없앨 수 있었습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 괜찮은 방법이라고 생각되네요! 더 좋은 방법이 떠오르지 않습니당 |
||
|
||
return ( | ||
<S.FooterContainer> | ||
<Text.Small color='inherit'> | ||
Copyright{' '} | ||
<Text.Small color='inherit' weight='bold'> | ||
Codezap | ||
</Text.Small>{' '} | ||
© All rights reserved. | ||
</Text.Small> | ||
<S.ContactEmail href='mailto:[email protected]'> | ||
<Text.Small color='inherit' weight='bold'> | ||
문의 : | ||
</Text.Small>{' '} | ||
<Text.Small color='inherit'>[email protected]</Text.Small>{' '} | ||
</S.ContactEmail> | ||
</S.FooterContainer> | ||
); | ||
}; | ||
|
||
export default Footer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,12 +3,10 @@ import { useNavigate } from 'react-router-dom'; | |
|
||
import { DEFAULT_SORTING_OPTION, SORTING_OPTIONS } from '@/api'; | ||
import { ArrowUpIcon, PlusIcon, SearchIcon, ZapzapCuriousLogo } from '@/assets/images'; | ||
import { Flex, Heading, Input, PagingButtons, Dropdown, Button, Modal, Text, LoadingBall } from '@/components'; | ||
import { Flex, Heading, Input, PagingButtons, Dropdown, Button, Modal, Text } from '@/components'; | ||
import { useWindowWidth, useDebounce, useToggle, useDropdown, useInput } from '@/hooks'; | ||
import { useAuth } from '@/hooks/authentication'; | ||
import { useCategoryListQuery } from '@/queries/categories'; | ||
import { useTagListQuery } from '@/queries/tags'; | ||
import { useTemplateDeleteMutation, useTemplateListQuery } from '@/queries/templates'; | ||
import { useTemplateDeleteMutation, useTemplateCategoryTagQueries } from '@/queries/templates'; | ||
import { END_POINTS } from '@/routes'; | ||
import { theme } from '@/style/theme'; | ||
import { scroll } from '@/utils'; | ||
|
@@ -36,18 +34,17 @@ const MyTemplatePage = () => { | |
|
||
const [page, setPage] = useState<number>(1); | ||
|
||
const { data: templateData, isPending } = useTemplateListQuery({ | ||
const [{ data: templateData }, { data: categoryData }, { data: tagData }] = useTemplateCategoryTagQueries({ | ||
keyword: debouncedKeyword, | ||
categoryId: selectedCategoryId, | ||
tagIds: selectedTagIds, | ||
sort: sortingOption.key, | ||
page, | ||
}); | ||
const { data: categoryData } = useCategoryListQuery(); | ||
const { data: tagData } = useTagListQuery(); | ||
const templates = templateData?.templates || []; | ||
const categories = categoryData?.categories || []; | ||
const tags = tagData?.tags || []; | ||
|
||
const templateList = templateData?.templates || []; | ||
const categoryList = categoryData?.categories || []; | ||
const tagList = tagData?.tags || []; | ||
const totalPages = templateData?.totalPages || 0; | ||
|
||
const { mutateAsync: deleteTemplates } = useTemplateDeleteMutation(selectedList); | ||
|
@@ -73,13 +70,13 @@ const MyTemplatePage = () => { | |
}; | ||
|
||
const handleAllSelected = () => { | ||
if (selectedList.length === templates.length) { | ||
if (selectedList.length === templateList.length) { | ||
setSelectedList([]); | ||
|
||
return; | ||
} | ||
|
||
setSelectedList(templates.map((template) => template.id)); | ||
setSelectedList(templateList.map((template) => template.id)); | ||
}; | ||
|
||
const handleDelete = () => { | ||
|
@@ -89,11 +86,7 @@ const MyTemplatePage = () => { | |
}; | ||
|
||
const renderTemplateContent = () => { | ||
if (isPending) { | ||
return <LoadingBall />; | ||
} | ||
|
||
if (templates.length === 0) { | ||
if (templateList.length === 0) { | ||
if (debouncedKeyword !== '') { | ||
return ( | ||
<Flex justify='center' align='center' padding='2rem'> | ||
|
@@ -108,7 +101,7 @@ const MyTemplatePage = () => { | |
|
||
return ( | ||
<TemplateGrid | ||
templates={templates} | ||
templateList={templateList} | ||
cols={getGridCols(windowWidth)} | ||
isEditMode={isEditMode} | ||
selectedList={selectedList} | ||
|
@@ -122,7 +115,7 @@ const MyTemplatePage = () => { | |
<TopBanner name={name ?? '나'} /> | ||
<S.MainContainer> | ||
<Flex direction='column' gap='2.5rem' style={{ marginTop: '4.5rem' }}> | ||
<CategoryFilterMenu categories={categories} onSelectCategory={handleCategoryMenuClick} /> | ||
<CategoryFilterMenu categoryList={categoryList} onSelectCategory={handleCategoryMenuClick} /> | ||
</Flex> | ||
|
||
<Flex direction='column' width='100%' gap='1rem'> | ||
|
@@ -133,7 +126,7 @@ const MyTemplatePage = () => { | |
돌아가기 | ||
</Button> | ||
<Button variant='outlined' size='small' onClick={handleAllSelected}> | ||
{selectedList.length === templates.length ? '전체 해제' : '전체 선택'} | ||
{selectedList.length === templateList.length ? '전체 해제' : '전체 선택'} | ||
</Button> | ||
<Button | ||
variant={selectedList.length ? 'contained' : 'text'} | ||
|
@@ -168,45 +161,28 @@ const MyTemplatePage = () => { | |
getOptionLabel={(option) => option.value} | ||
/> | ||
</Flex> | ||
{tags.length !== 0 && ( | ||
<TagFilterMenu tags={tags} selectedTagIds={selectedTagIds} onSelectTags={handleTagMenuClick} /> | ||
{tagList.length !== 0 && ( | ||
<TagFilterMenu tagList={tagList} selectedTagIds={selectedTagIds} onSelectTags={handleTagMenuClick} /> | ||
)} | ||
{renderTemplateContent()} | ||
|
||
{templates.length !== 0 && ( | ||
{templateList.length !== 0 && ( | ||
<Flex justify='center' gap='0.5rem' margin='1rem 0'> | ||
<PagingButtons currentPage={page} totalPages={totalPages} onPageChange={handlePageChange} /> | ||
</Flex> | ||
)} | ||
</Flex> | ||
|
||
{isDeleteModalOpen && ( | ||
<Modal isOpen={isDeleteModalOpen} toggleModal={toggleDeleteModal} size='xsmall'> | ||
<Flex direction='column' justify='space-between' align='center' margin='1rem 0 0 0' gap='2rem'> | ||
<Flex direction='column' justify='center' align='center' gap='0.75rem'> | ||
<Text.Large color='black' weight='bold'> | ||
정말 삭제하시겠습니까? | ||
</Text.Large> | ||
<Text.Medium color='black'>삭제된 템플릿은 복구할 수 없습니다.</Text.Medium> | ||
</Flex> | ||
<Flex justify='center' align='center' gap='0.5rem'> | ||
<Button variant='outlined' onClick={toggleDeleteModal}> | ||
취소 | ||
</Button> | ||
<Button onClick={handleDelete}>삭제</Button> | ||
</Flex> | ||
</Flex> | ||
</Modal> | ||
<ConfirmDeleteModal | ||
isDeleteModalOpen={isDeleteModalOpen} | ||
toggleDeleteModal={toggleDeleteModal} | ||
handleDelete={handleDelete} | ||
/> | ||
)} | ||
</S.MainContainer> | ||
|
||
<S.ScrollTopButton | ||
onClick={() => { | ||
scroll.top('smooth'); | ||
}} | ||
> | ||
<ArrowUpIcon aria-label='맨 위로' /> | ||
</S.ScrollTopButton> | ||
<ScrollTopButton /> | ||
</S.MyTemplatePageContainer> | ||
); | ||
}; | ||
|
@@ -240,3 +216,38 @@ const NewTemplateButton = () => { | |
}; | ||
|
||
export default MyTemplatePage; | ||
|
||
interface ConfirmDeleteModalProps { | ||
isDeleteModalOpen: boolean; | ||
toggleDeleteModal: () => void; | ||
handleDelete: () => void; | ||
} | ||
|
||
const ConfirmDeleteModal = ({ isDeleteModalOpen, toggleDeleteModal, handleDelete }: ConfirmDeleteModalProps) => ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요 모달은 따로 서브 컴포넌트로 파일 분리 안해도 괜찮을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 앗, 서브컨포넌트 분리하던거 다 reset 한줄 알았는데 아래 남아있었군요! |
||
<Modal isOpen={isDeleteModalOpen} toggleModal={toggleDeleteModal} size='xsmall'> | ||
<Flex direction='column' justify='space-between' align='center' margin='1rem 0 0 0' gap='2rem'> | ||
<Flex direction='column' justify='center' align='center' gap='0.75rem'> | ||
<Text.Large color='black' weight='bold'> | ||
정말 삭제하시겠습니까? | ||
</Text.Large> | ||
<Text.Medium color='black'>삭제된 템플릿은 복구할 수 없습니다.</Text.Medium> | ||
</Flex> | ||
<Flex justify='center' align='center' gap='0.5rem'> | ||
<Button variant='outlined' onClick={toggleDeleteModal}> | ||
취소 | ||
</Button> | ||
<Button onClick={handleDelete}>삭제</Button> | ||
</Flex> | ||
</Flex> | ||
</Modal> | ||
); | ||
|
||
const ScrollTopButton = () => ( | ||
<S.ScrollTopButton | ||
onClick={() => { | ||
scroll.top('smooth'); | ||
}} | ||
> | ||
<ArrowUpIcon aria-label='맨 위로' /> | ||
</S.ScrollTopButton> | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
놓친 부분이 있었네요~!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
놓친부분이라기보다는 백엔드에서 요구사항이 변경에 따른 변화입니다..!ㅎㅎ
이전에는 키워드가 없어도 반드시 쿼리에 추가해서 보내달라고했는데,
이번에 리팩토링하면서 키워드가 없을때 주지 않도록 해달라고 하여 변경하게 되었습니다!ㅎㅎ