-
Notifications
You must be signed in to change notification settings - Fork 5
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
feat: 전역 suspense 개선 #427
The head ref may contain hidden characters: "feature/426-\uC804\uC5ED_suspense_\uAC1C\uC120"
feat: 전역 suspense 개선 #427
Changes from all commits
5954faf
6b6b962
82f5a9a
9cdebe4
24c3fef
e608b96
b11d4d4
e040fef
dd1c42b
c4f28a0
cf91a54
236b4a8
c6fb2ab
a4209de
594bd4a
3130327
19356c1
37b8f87
18772b6
911b4af
17d4a20
8e8bd16
b43776c
23630ae
e19cf6b
eb0e819
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 |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { keyframes, styled } from 'styled-components'; | ||
|
||
export const ProgressBar = styled.div` | ||
position: fixed; | ||
z-index: ${(props) => props.theme.zIndex.tooltip}; | ||
top: 0; | ||
left: 0; | ||
|
||
width: 100%; | ||
height: 3px; | ||
|
||
background-color: ${(props) => props.theme.color.primary}; | ||
border-radius: 0 4px 4px 0; | ||
`; | ||
|
||
export const progressing = keyframes` | ||
0% { transform: translateX(-100%); } | ||
50% { transform: translateX(-20%); } | ||
100% { transform: translateX(0); } | ||
`; | ||
|
||
export const Progressing = styled(ProgressBar)` | ||
animation: ${progressing} 6s ease-out; | ||
`; | ||
|
||
export const fillOut = keyframes` | ||
0% { | ||
opacity: 1; | ||
transform: translateX(-100%); | ||
} | ||
50% { | ||
opacity: 1; | ||
transform: translateX(0); | ||
} | ||
100% { | ||
opacity: 0; | ||
transform: translateX(0); | ||
} | ||
`; | ||
|
||
export const Finish = styled(ProgressBar)<{ $animationTime: number }>` | ||
animation: ${fillOut} ${(props) => props.$animationTime}ms; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { useEffect, useMemo } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
import { useRecoilValue } from 'recoil'; | ||
import { Finish, Progressing } from './PageLoadingBar.style'; | ||
import { isShowPageLoadingState } from 'store/atoms/@common'; | ||
import useToggle from 'hooks/@common/useToggle'; | ||
|
||
export const FINISH_ANIMATION_TIME = 600; | ||
|
||
const PageLoadingBar = () => { | ||
const isShowPageLoading = useRecoilValue(isShowPageLoadingState); | ||
|
||
const { isOn: isShow, on: show, off: hide } = useToggle(); | ||
const { isOn: isShowFinish, on: showFinish, off: hideFinish } = useToggle(); | ||
|
||
const root = useMemo(() => document.getElementById('root')!, []); | ||
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. document.body가 아니라 react root element에 넣는 이유가 궁금해요 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. 특별한 이유는 없었습니다! 혹시 body에 넣으면 장단점이 있을까요? 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.
|
||
|
||
useEffect(() => { | ||
if (isShowPageLoading) { | ||
show(); | ||
hideFinish(); | ||
return; | ||
} | ||
|
||
showFinish(); | ||
const hideId = setTimeout(hide, FINISH_ANIMATION_TIME / 2); | ||
const hideFinishId = setTimeout(hideFinish, FINISH_ANIMATION_TIME); | ||
|
||
return () => { | ||
clearTimeout(hideId); | ||
clearTimeout(hideFinishId); | ||
}; | ||
}, [isShowPageLoading, show, hide, showFinish, hideFinish]); | ||
|
||
return createPortal( | ||
<> | ||
{isShow && <Progressing />} | ||
{isShowFinish && <Finish $animationTime={FINISH_ANIMATION_TIME} />} | ||
</>, | ||
root | ||
); | ||
}; | ||
|
||
export default PageLoadingBar; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { PropsWithChildren, useEffect } from 'react'; | ||
import { useSetRecoilState } from 'recoil'; | ||
import { isShowPageLoadingState, lastPageState } from 'store/atoms/@common'; | ||
|
||
const PageLogger = (props: PropsWithChildren) => { | ||
const { children } = props; | ||
const setLastPage = useSetRecoilState(lastPageState); | ||
const setIsShowPageLoadingState = useSetRecoilState(isShowPageLoadingState); | ||
|
||
useEffect(() => { | ||
setLastPage(children); | ||
setIsShowPageLoadingState(false); | ||
}, [children, setLastPage, setIsShowPageLoadingState]); | ||
|
||
return children; | ||
}; | ||
|
||
export default PageLogger; |
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. R해당 파일은 페이지 보다는 fallback을 나타내는 Loading component같은데 component로 옮기는건 어떤가요? 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. 어렵네요.. RootTemplate의 Outlet이 전부 페이지면서, Outlet 대신 들어가는 fallback이라 페이지라고 생각했어요! (원래의 Loading이 페이지에 있기도 했구요) 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. 전 일반적인 페이지라고 한다면 고유한 url이 있어야 한다고 생각하는데 쵸파가 생각하는 페이지의 기준은 무엇인가요? (확실히 전역을 감싸는 에러 페이지나 전역 Suspense는 좀 애매하긴 하네요) 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. Outlet에 들어가는 내용이 페이지라고 생각했는데 url 기준도 좋네요! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { useEffect } from 'react'; | ||
import { useRecoilValue, useSetRecoilState } from 'recoil'; | ||
import Loading from 'pages/@common/Loading'; | ||
import { isShowPageLoadingState, lastPageState } from 'store/atoms/@common'; | ||
|
||
const LastPageLoading = () => { | ||
const lastPage = useRecoilValue(lastPageState); | ||
const setIsShowPageLoading = useSetRecoilState(isShowPageLoadingState); | ||
|
||
useEffect(() => { | ||
setIsShowPageLoading(true); | ||
|
||
return () => { | ||
setIsShowPageLoading(false); | ||
}; | ||
}, [setIsShowPageLoading]); | ||
|
||
return lastPage ?? <Loading />; | ||
}; | ||
|
||
export default LastPageLoading; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import { Link } from 'react-router-dom'; | ||
import styled from 'styled-components'; | ||
|
||
export const Wrapper = styled.main` | ||
export const Main = styled.main` | ||
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. C컴포넌트 이름을 바꾼 이유가 있나요? 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.
페이지마다 헤더와 푸터가 다르기 때문에 헤더와 푸터도 페이지의 구성요소라고 생각했습니다. |
||
position: relative; | ||
|
||
display: flex; | ||
|
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.
C
root엘리먼트가 없을 리가 없으니까 굳이 !를 사용하지 않고 단언을 사용해도 될 것 같은데 어떻게 생각하시나요?
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.
사실 없을리가 없으니 지금은 둘다 비슷할 것 같긴 하네요..
타입 자체를 바꿀 수 있는 단언보다, 타입은 같지만 있다는걸 확신해주는 !를 사용하는게 조금 더 안전한 코드라고 생각했습니다~