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

[Feature/BAR-2] Async Boundary 구현 #1

Merged
merged 1 commit into from
Dec 10, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/components/AsyncBoundary/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { ReactNode } from 'react';
import { Component, type PropsWithChildren } from 'react';

import CommonErrorScreen from './ErrorScreen';

interface ErrorBoundaryProps {
errorFallBack?: ReactNode;
onError?: (error: Error) => void;
}

class ErrorBoundary extends Component<
PropsWithChildren<ErrorBoundaryProps>,
{ error: Error | null }
> {
error = null;

componentDidCatch(error: Error) {
if (this.props.onError) {
this.setState({
error,
});
}
}

render() {
const { error } = this.state;

if (error) {
if (this.props.errorFallBack) {
return this.props.errorFallBack;
}

return <CommonErrorScreen error={error} />;
Copy link
Member Author

Choose a reason for hiding this comment

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

loading과 마찬가지로 팩토리가 필요.
추후 추가할 예정입니다 !

}

return this.props.children;
}
}

export default ErrorBoundary;
14 changes: 14 additions & 0 deletions src/components/AsyncBoundary/components/ErrorScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
interface CommonErrorScreenProps {
error: Error;
}

// TODO: 의도되지 않은 에러에 대한 공통 스크린 정의 (404, 400, 500 등은 에러 페이지로 구현)
const CommonErrorScreen = ({ error }: CommonErrorScreenProps) => {
if (!error) {
window.location.reload();
}

return <>{JSON.stringify(error)}</>;
};

export default CommonErrorScreen;
21 changes: 21 additions & 0 deletions src/components/AsyncBoundary/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { type PropsWithChildren, type ReactNode, Suspense } from 'react';

import LoadingView from '../Loading';
Copy link
Member

Choose a reason for hiding this comment

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

Loading과 LoadingView 중 하나로 통일하는 건 어떤가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

Loading은 폴더명으로 도메인적 맥락을 가져갑니다!
LoadingView는 로딩 상태에 대한 뷰 컴포넌트로 팩토리 역할을 하는 컴포넌트여서 다르게 명명했습니다.

혹시 통일하는게 더 명시적일까요 ??

import ErrorBoundary from './components/ErrorBoundary';

interface AsyncBoundaryProps {
loadingFallback?: ReactNode;
}

const AsyncBoundary = ({
children,
loadingFallback = <LoadingView />,
}: PropsWithChildren<AsyncBoundaryProps>) => {
return (
<ErrorBoundary>
<Suspense fallback={loadingFallback}>{children}</Suspense>
</ErrorBoundary>
);
};

export default AsyncBoundary;
5 changes: 5 additions & 0 deletions src/components/Loading/components/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Spinner = () => {
return <>spinner</>;
};

export default Spinner;
18 changes: 18 additions & 0 deletions src/components/Loading/index.tsx
Copy link
Member Author

Choose a reason for hiding this comment

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

이후 케이스 추가가 필요합니다.

AsyncBoundary뿐 아니라 별도의 컴포넌트로 도 사용될 수 있게 분리

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { FC } from 'react';

import Spinner from './components/Spinner';

type LoadingViewType = 'spinner';

interface LoadingViewProps {
type?: LoadingViewType;
}

const LoadingView: FC<LoadingViewProps> = ({ type = 'spinner' }) => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const LoadingView: FC<LoadingViewProps> = ({ type = 'spinner' }) => {
const LoadingView = ({ type = 'spinner' }: LoadingViewProps) => {}

React.FC는 지양하는 게 좋아서 이렇게 작성하면 어떨까요?
요기 참고하면 좋을 것 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

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

우선 토픽 공유주셔서 감사해요 ! 알고 있던 토픽인데 현재는 해당하지 않는 이슈입니다.
DefinitelyTyped/DefinitelyTyped#56210

컨벤션 영역이라고 생각되어서 차주 회의에 얘기해보면 좋을것 같습니다.

Copy link
Member Author

Choose a reason for hiding this comment

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

요약하면 React18부터는 children을 암묵적으로 가지지 않습니다.

switch (type) {
default:
return <Spinner />;
}
};

export default LoadingView;
Empty file removed src/components/example.tsx
Empty file.