-
Notifications
You must be signed in to change notification settings - Fork 4
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/CK-187] Error-Boundary를 활용한 에러핸들링(초안) #148
Changes from all commits
603cedd
cbff71e
29bcf37
9318eee
434ddce
c6328f0
c5cbfc4
67e143b
5c94f86
0acfb94
9d61d52
4ac964c
d30e342
9e3f44d
feb1c03
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,75 @@ | ||
import * as S from './errorComponents.styles'; | ||
import elephantImage from '../../../assets/images/cryingelephant.png'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
export const NotFound = () => { | ||
const navigate = useNavigate(); | ||
|
||
const moveMainPage = () => { | ||
navigate('/'); | ||
window.location.reload(); | ||
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. ..ㅎㅎ 수정하겠습니다아 |
||
}; | ||
return ( | ||
<S.Container> | ||
<S.ElephantImage src={elephantImage} alt='crying-elephant' /> | ||
<S.NotFoundTitle>404 Not Found</S.NotFoundTitle> | ||
<S.NotFoundText>잘못된 경로 접근했어요</S.NotFoundText> | ||
<S.MovePageButton onClick={moveMainPage}>메인페이지로 돌아가기</S.MovePageButton> | ||
</S.Container> | ||
); | ||
}; | ||
|
||
export const ServerError = () => { | ||
const navigate = useNavigate(); | ||
|
||
const moveMainPage = () => { | ||
navigate('/'); | ||
window.location.reload(); | ||
}; | ||
Comment on lines
+25
to
+28
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. 앗 어차피 저 reload부분이 리셋로직으로 대체될꺼라서 임시방편으로 그냥 뒀는데요..!! 훅이 필요할까요!? 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.Container> | ||
<S.ElephantImage src={elephantImage} alt='crying-elephant' /> | ||
<S.SereverTitle>500 Error</S.SereverTitle> | ||
<S.ServerText>서버에서 오류가 발생했어요</S.ServerText> | ||
<S.MovePageButton onClick={moveMainPage}>메인페이지로 돌아가기</S.MovePageButton> | ||
</S.Container> | ||
); | ||
}; | ||
|
||
export const Runtime = () => { | ||
const navigate = useNavigate(); | ||
|
||
const moveMainPage = () => { | ||
navigate('/'); | ||
window.location.reload(); | ||
}; | ||
return ( | ||
<S.Container> | ||
<S.ElephantImage src={elephantImage} alt='crying-elephant' /> | ||
<S.RuntimeTitle>Error</S.RuntimeTitle> | ||
<S.RuntimeText> | ||
Comment on lines
+47
to
+50
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. 마크업 계층구조도 반복되는 느낌이 드는데, HOC 와 같은 방식을 추후에 적용해보든건 어떨까여?? 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. 호호~ 좋은 생각이에요 고려해보겠습니다!! |
||
죄송합니다, 페이지를 로드하는 동안 오류가 발생했습니다 | ||
</S.RuntimeText> | ||
<S.MovePageButton onClick={moveMainPage}>메인페이지로 돌아가기</S.MovePageButton> | ||
</S.Container> | ||
); | ||
}; | ||
|
||
export const Critical = () => { | ||
const navigate = useNavigate(); | ||
|
||
const moveMainPage = () => { | ||
navigate('/'); | ||
window.location.reload(); | ||
}; | ||
return ( | ||
<S.Container> | ||
<S.ElephantImage src={elephantImage} alt='crying-elephant' /> | ||
<S.CriticalTitle>Service Not Working</S.CriticalTitle> | ||
<S.CriticalText> | ||
죄송합니다, 알 수 없는 이유로 서비스 사용이 불가능합니다 | ||
</S.CriticalText> | ||
<S.MovePageButton onClick={moveMainPage}>메인페이지로 돌아가기</S.MovePageButton> | ||
</S.Container> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const Container = styled.section` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
|
||
width: 100%; | ||
height: 100vh; | ||
`; | ||
|
||
export const ElephantImage = styled.img` | ||
width: 20%; | ||
`; | ||
|
||
export const NotFoundTitle = styled.h1` | ||
${({ theme }) => theme.fonts.title_large}; | ||
font-size: 4rem; | ||
color: ${({ theme }) => theme.colors.main_dark}; | ||
`; | ||
|
||
export const NotFoundText = styled.h2` | ||
${({ theme }) => theme.fonts.h2}; | ||
color: ${({ theme }) => theme.colors.gray300}; | ||
`; | ||
|
||
export const SereverTitle = styled.h1` | ||
${({ theme }) => theme.fonts.title_large}; | ||
font-size: 4rem; | ||
color: ${({ theme }) => theme.colors.main_dark}; | ||
`; | ||
|
||
export const ServerText = styled.h2` | ||
${({ theme }) => theme.fonts.h2}; | ||
color: ${({ theme }) => theme.colors.gray300}; | ||
`; | ||
|
||
export const RuntimeTitle = styled.h1` | ||
${({ theme }) => theme.fonts.title_large}; | ||
font-size: 4rem; | ||
color: ${({ theme }) => theme.colors.main_dark}; | ||
`; | ||
|
||
export const RuntimeText = styled.h2` | ||
${({ theme }) => theme.fonts.h2}; | ||
color: ${({ theme }) => theme.colors.gray300}; | ||
`; | ||
|
||
export const CriticalTitle = styled.h1` | ||
${({ theme }) => theme.fonts.title_large}; | ||
font-size: 4rem; | ||
color: ${({ theme }) => theme.colors.main_dark}; | ||
`; | ||
|
||
export const CriticalText = styled.h2` | ||
${({ theme }) => theme.fonts.h2}; | ||
color: ${({ theme }) => theme.colors.gray300}; | ||
`; | ||
|
||
export const MovePageButton = styled.button` | ||
${({ theme }) => theme.fonts.button1} | ||
margin: 2rem 0; | ||
padding: 1rem 2rem; | ||
|
||
color: ${({ theme }) => theme.colors.white}; | ||
|
||
background-color: ${({ theme }) => theme.colors.main_middle}; | ||
border-radius: 30px; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { PropsWithChildren, Suspense } from 'react'; | ||
import Spinner from '../spinner/Spinner'; | ||
import CriticalErrorBoundary from './CriticalErrorBoundary'; | ||
import NotFoundErrorBoundary from './NotFoundErrorBoundary'; | ||
import RuntimeErrorBoundary from './RuntimeErrorBoundary'; | ||
import ServerErrorBoundary from './ServerErrorBoundary'; | ||
|
||
const AsyncBoundary = ({ children }: PropsWithChildren) => { | ||
return ( | ||
<CriticalErrorBoundary> | ||
<RuntimeErrorBoundary> | ||
<ServerErrorBoundary> | ||
<NotFoundErrorBoundary> | ||
<Suspense fallback={<Spinner />}>{children}</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. 이렇게 되면, 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. 맞아요오..!!! 이 AsyncBoundary를 필요한 곳에 부분적으로 감싸줘야하는데 아직 완성이 되지 않아서 일단 app 전체를 감싸줬어요! |
||
</NotFoundErrorBoundary> | ||
</ServerErrorBoundary> | ||
</RuntimeErrorBoundary> | ||
</CriticalErrorBoundary> | ||
); | ||
}; | ||
|
||
export default AsyncBoundary; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ErrorInfo } from 'react'; | ||
import { Critical } from '../error/ErrorComponents'; | ||
import ErrorBoundary from './ErrorBoundary'; | ||
|
||
class CriticalErrorBoundary extends ErrorBoundary { | ||
componentDidCatch(_error: any, _errorInfo: ErrorInfo): void {} | ||
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. 사용하지 않는 매개변수때문에 린트가 징징대서 _를 넣어줬어요..!! 추후에 에러 처리 로직이 들어가야하는 부분이라서요!! |
||
|
||
render() { | ||
const { didCatch } = this.state; | ||
const { children } = this.props; | ||
if (didCatch) { | ||
return <Critical />; | ||
} | ||
return children; | ||
} | ||
} | ||
|
||
export default CriticalErrorBoundary; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { ErrorInfo } from 'react'; | ||
import { NotFound } from '../error/ErrorComponents'; | ||
import ErrorBoundary from './ErrorBoundary'; | ||
|
||
class NotFoundErrorBoundary extends ErrorBoundary { | ||
componentDidCatch(error: any, _errorInfo: ErrorInfo): void { | ||
if (error.response.status !== 404) throw error; | ||
} | ||
|
||
render() { | ||
const { didCatch } = this.state; | ||
const { children } = this.props; | ||
if (didCatch) { | ||
return <NotFound />; | ||
} | ||
return children; | ||
} | ||
} | ||
|
||
export default NotFoundErrorBoundary; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ErrorInfo } from 'react'; | ||
import { Runtime } from '../error/ErrorComponents'; | ||
import ErrorBoundary from './ErrorBoundary'; | ||
|
||
class RuntimeErrorBoundary extends ErrorBoundary { | ||
componentDidCatch(_error: any, _errorInfo: ErrorInfo): void {} | ||
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. 저도그래요! 지워보겠습니다~! |
||
|
||
render() { | ||
const { didCatch } = this.state; | ||
const { children } = this.props; | ||
if (didCatch) { | ||
return <Runtime />; | ||
} | ||
return children; | ||
} | ||
} | ||
|
||
export default RuntimeErrorBoundary; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { SERVER_ERROR_CODE } from '@/constants/_common/regex'; | ||
import { ErrorInfo } from 'react'; | ||
import { ServerError } from '../error/ErrorComponents'; | ||
import ErrorBoundary from './ErrorBoundary'; | ||
|
||
class ServerErrorBoundary extends ErrorBoundary { | ||
componentDidCatch(error: any, _errorInfo: ErrorInfo): void { | ||
if (!SERVER_ERROR_CODE.test(error.response.status)) throw error; | ||
} | ||
|
||
render() { | ||
const { didCatch } = this.state; | ||
const { children } = this.props; | ||
if (didCatch) { | ||
return <ServerError />; | ||
} | ||
return children; | ||
} | ||
} | ||
|
||
export default ServerErrorBoundary; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const SERVER_ERROR_CODE = /5\d{2}/; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { ErrorBoundaryContextType } from '@/myTypes/_common/errorBoundary'; | ||
import { createContext } from 'react'; | ||
|
||
export const ErrorBoundaryContext = createContext<ErrorBoundaryContextType | null>(null); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,8 +22,15 @@ const startApp = async () => { | |
staleTime: 1000 * 60 * 5, | ||
cacheTime: 1000 * 60 * 30, | ||
}, | ||
|
||
mutations: { | ||
useErrorBoundary: true, | ||
useErrorBoundary: false, | ||
onError: (e) => { | ||
const error = e as any; | ||
if (error.response.status === 400) { | ||
alert(error.response.data.message); | ||
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. alert 말고 다른 방식은 없을까요??! 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. 엉 이거 토스트로 변경하려구 했는데, 애초에 우리가 만들어둔 토스트 자체가 ToastProvider 안에서만 쓸 수 있는데 이 queryClient는 그 밖에서 선언되고있어서 이 계층에서 토스트 사용은 불가능하더라구요..!! 일단 alert로 두고 토스트를 사용할 방법을 고민해볼께요 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 comment
The reason will be displayed to describe this comment to others. Learn more.
넘 좋네요!
부엉이 말대로 중복만 조금 제거해주면 더 좋을 것 같아요🤩