Skip to content

Commit

Permalink
feat: Async Boundary 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
wonjin-dev committed Dec 10, 2023
1 parent 308b571 commit 0e1b74e
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
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} />;
}

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';
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
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' }) => {
switch (type) {
default:
return <Spinner />;
}
};

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

0 comments on commit 0e1b74e

Please sign in to comment.