Skip to content

Commit

Permalink
Refactor/#125-re: 401 에러 시 자동 로그아웃 및 재 로그인 유도 기능 추가 (#129)
Browse files Browse the repository at this point in the history
* refactor: NeedAuth 기능을 ApiErrorBoundary에 위임

미로그인 사용자는 401 에러가 발생하므로 이를 ApiErrorBoundary에서 감지하여 라우팅할 수 있도록 합니다.

* refactor: Login 페이지에서 메인페이지로 가는 링크 텍스트 추가
  • Loading branch information
semnil5202 authored Apr 29, 2024
1 parent 96bae0b commit 8794a32
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 69 deletions.
21 changes: 16 additions & 5 deletions src/components/ErrorBoundary/ApiErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type State =
}
| {
error: AxiosError;
errorDetail: 'network' | 'unauthorized';
errorDetail: 'server' | 'unauthorized' | 'auth-expired';
};

class ErrorBoundary extends Component<Props, State> {
Expand Down Expand Up @@ -59,16 +59,23 @@ class ErrorBoundary extends Component<Props, State> {
}

if (error.response?.status === 401) {
if (!localStorage.getItem('userToken')) {
return {
error,
errorDetail: 'unauthorized',
};
}

return {
error,
errorDetail: 'unauthorized',
errorDetail: 'auth-expired',
};
}

if (error.response?.status >= 400) {
return {
error,
errorDetail: 'network',
errorDetail: 'server',
};
}
}
Expand All @@ -82,7 +89,7 @@ class ErrorBoundary extends Component<Props, State> {
componentDidCatch(): void {
const { errorDetail } = this.state;

if (errorDetail === 'unauthorized') {
if (errorDetail === 'auth-expired') {
localStorage.removeItem('userToken');
localStorage.removeItem('user');

Expand All @@ -96,6 +103,10 @@ class ErrorBoundary extends Component<Props, State> {
}

if (this.state.errorDetail === 'unauthorized') {
return <Navigate to="/login" />;
}

if (this.state.errorDetail === 'auth-expired') {
return (
<>
<UnauthorizedAlert />
Expand All @@ -104,7 +115,7 @@ class ErrorBoundary extends Component<Props, State> {
);
}

if (this.state.errorDetail === 'network') {
if (this.state.errorDetail === 'server') {
if (this.props.fallback) {
const FallbackComponent = this.props.fallback.type;
const fallbackProps = {
Expand Down
13 changes: 13 additions & 0 deletions src/pages/Login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import styled from '@emotion/styled';
import { Spacer, Text, theme, SVGLoginKakao, SVGLoginNaver, SVGLoginLogo, Flex } from 'concept-be-design-system';
import { useNavigate } from 'react-router-dom';

import SEOMeta from '../../components/SEOMeta/SEOMeta';
import { BASE_URL } from '../../constants';

const REQUEST_URL = `${BASE_URL}/oauth/kakao`;

const Login = () => {
const navigate = useNavigate();

const onClickOauthKakao = () => {
window.location.href = REQUEST_URL;
};
Expand Down Expand Up @@ -37,6 +40,11 @@ const Login = () => {
<Text font="suit15rb">네이버 로그인</Text>
</TextWrapper>
</ButtonWrapper>

<Spacer size={40} />
<LinkText font="suit14r" color="b6" onClick={() => navigate('/')}>
메인페이지로 가기
</LinkText>
</Flex>
</>
);
Expand Down Expand Up @@ -75,3 +83,8 @@ const TextWrapper = styled.div`
height: 100%;
width: 100%;
`;

const LinkText = styled(Text)`
text-decoration: underline;
cursor: pointer;
`;
26 changes: 0 additions & 26 deletions src/pages/NeedAuth.tsx

This file was deleted.

40 changes: 2 additions & 38 deletions src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import FeedDetailPage from './pages/FeedDetail/FeedDetail.page';
import Agreement from './pages/Login/Agreement';
import KakaoRedirect from './pages/Login/KakaoRedirect';
import Login from './pages/Login/Login';
import NeedAuth from './pages/NeedAuth';
import NotFound from './pages/NotFound';
import More from './pages/Profile/More.page';
import Profile from './pages/Profile/Profile.page';
Expand All @@ -21,10 +20,9 @@ import WriteEditPage from './pages/WriteEdit/WriteEdit.page';
interface RouteElement {
path: string;
element: ReactNode;
isAuth: boolean;
redirectPath?: string;
errorElement?: ReactNode;
children: { path: string; element: ReactNode; withAuth: boolean }[];
children: { path: string; element: ReactNode }[];
}

const withAsyncBoundary = (children: ReactNode) => (
Expand All @@ -37,90 +35,56 @@ const routes: RouteElement[] = [
{
path: '/',
element: <MobileView />,
isAuth: false,
errorElement: <NotFound />,
children: [
{
path: '',
element: withAsyncBoundary(<Feed />),
withAuth: false,
},
{
path: '/feed/:id',
element: withAsyncBoundary(<FeedDetailPage />),
withAuth: true,
},
{
path: '/write',
element: withAsyncBoundary(<WritePage />),
withAuth: true,
},
{
path: '/write-edit',
element: withAsyncBoundary(<WriteEditPage />),
withAuth: true,
},
{
path: '/login',
element: <Login />,
withAuth: false,
},
{
path: '/oauth/redirected/kakao',
element: <KakaoRedirect />,
withAuth: false,
},
{
path: '/profile/:id',
element: withAsyncBoundary(<Profile />),
withAuth: true,
},
{
path: '/profile-edit',
element: withAsyncBoundary(<ProfileEdit />),
withAuth: true,
},
{
path: '/profile/:id/more',
element: <More />,
withAuth: true,
},

{
path: '/agreement',
element: <Agreement />,
withAuth: false,
},
{
path: '/sign-up',
element: withAsyncBoundary(<SignUpPage />),
withAuth: false,
},
],
},
];

const router = createBrowserRouter(
routes.map((route) => {
const childrenRoutes = route.children?.map((childRoute) => {
if (childRoute.withAuth) {
return {
path: childRoute.path,
element: <NeedAuth withAuth={childRoute.withAuth}>{childRoute.element}</NeedAuth>,
};
}

return {
path: childRoute.path,
element: childRoute.element,
};
});

return {
...route,
children: childrenRoutes,
};
}),
);
const router = createBrowserRouter(routes);

export default router;

0 comments on commit 8794a32

Please sign in to comment.