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

refactor(my-page): my-page suspense 적용 및 root page server component로 변경 #392

Draft
wants to merge 8 commits into
base: release/routing
Choose a base branch
from
4 changes: 2 additions & 2 deletions src/app/(AppBarHeader)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Appbar } from './_components/Appbar';
import { CategoryBottomSheet } from './toks-main/_components/CategoryBottomSheet';

export default function AppBarLayout({ children }: StrictPropsWithChildren) {
return (
<>
<Appbar />
{children}
<CategoryBottomSheet />
{/* TODO: 에러 고치기 .. */}
{/* <CategoryBottomSheet /> */}
</>
);
}
33 changes: 33 additions & 0 deletions src/app/(BackHeader)/my-page/@toast/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use client';

import React, { useEffect, useState } from 'react';

import { useToast } from '@/common';
import { Toast as ToastComponent, ToastProps } from '@/common/components/Toast';

const Toast = () => {
const { getSavedToastInfo, clearSavedToast } = useToast();
const [toastData, setToastData] = useState<ToastProps | null>(null);

useEffect(() => {
setToastData(getSavedToastInfo());

clearSavedToast();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

if (toastData === null) {
return null;
}

return (
<ToastComponent
isShow={toastData.isShow}
type={toastData.type}
direction={toastData.direction}
title={toastData.title}
/>
);
};

export default Toast;
53 changes: 53 additions & 0 deletions src/app/(BackHeader)/my-page/@userInfo/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client';

import { getCookie } from 'cookies-next';
import Image from 'next/image';
import { useRouter } from 'next/navigation';

import { ICON_URL } from '@/common';
import { Text } from '@/common/components/Text';

import { SkeletonUserInfo } from '../_components/SkeletonUserInfo.tsx';
import { useSuspenseUserInfoQuery } from '../_lib/hooks/useSuspenseUserInfoQuery';

const UserInfo = () => {
const router = useRouter();
const accessToken = getCookie('accessToken');
const { data: userInfo } = useSuspenseUserInfoQuery(accessToken as string);

if (!userInfo) {
return <SkeletonUserInfo />;
}
return (
<div className="w-full flex-col items-center pt-20px text-center">
<div className="mx-auto mb-24px h-96px w-96px overflow-hidden rounded-full">
<Image
src={userInfo ? userInfo.profileImageUrl : ICON_URL.EMOJI_BASE_GRAY}
alt="프로필 이미지"
width={96}
height={96}
/>
</div>
<div className="mb-8px flex h-24px w-full justify-center">
<Text typo="headingL" color="gray10">
{userInfo?.nickname}
</Text>
<Image
className="ml-4px"
src={ICON_URL.CHEVRON_RIGHT}
alt="닉네임 수정 버튼"
width={24}
height={24}
onClick={() => router.push('/nickname/update')}
/>
</div>
<div className="h-24px">
<Text typo="body" color="gray40">
{userInfo?.email}
</Text>
</div>
</div>
);
};

export default UserInfo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';
import { useRouter } from 'next/navigation';

import { GOOGLE_FORM_URL } from '@/common';
import { Button } from '@/common/components/Button';

export const GoogleFormButton = () => {
const router = useRouter();

return (
<Button
className="w-full"
size="L"
typo="subheadingBold"
backgroundColor="primaryDefault"
onClick={() => {
router.push(GOOGLE_FORM_URL);
}}
>
이런 퀴즈가 있었으면 좋겠어요
</Button>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Image from 'next/image';

import { ICON_URL } from '@/common';
import { Skeleton } from '@/common/components/Skeleton';

export const SkeletonUserInfo = () => {
return (
<div className="flex w-full animate-pulse flex-col items-center pt-20px text-center">
<div className="mx-auto mb-24px h-96px w-96px overflow-hidden rounded-full">
<Image
src={ICON_URL.EMOJI_BASE_GRAY}
alt="프로필 이미지"
width={96}
height={96}
/>
</div>
<div className="flex w-full flex-col items-center">
<Skeleton className="mb-[8px] h-[24px] w-[120px]" />
<Skeleton className="m-[4px] h-[16px] w-[200px]" />
</div>
</div>
);
};
45 changes: 0 additions & 45 deletions src/app/(BackHeader)/my-page/_components/UserInfo/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useSuspenseQuery } from '@tanstack/react-query';

import { getUserInfo } from '@/common';

export const useSuspenseUserInfoQuery = (accessToken?: string) => {
return useSuspenseQuery({
queryKey: ['userInfo', accessToken],
queryFn: getUserInfo,
});
};
22 changes: 22 additions & 0 deletions src/app/(BackHeader)/my-page/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { PropsWithChildren, Suspense } from 'react';

import { SkeletonUserInfo } from './_components/SkeletonUserInfo.tsx';

type Props = {
toast: React.ReactNode;
userInfo: React.ReactNode;
};

export default function MyPageLayout({
children,
toast,
userInfo,
}: PropsWithChildren<Props>) {
return (
<>
<Suspense fallback={<SkeletonUserInfo />}>{userInfo}</Suspense>
{children}
{toast}
</>
);
}
40 changes: 3 additions & 37 deletions src/app/(BackHeader)/my-page/page.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,15 @@
'use client';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

import { GOOGLE_FORM_URL, ICON_URL } from '@/common';
import { Button } from '@/common/components/Button';
import { ICON_URL } from '@/common';
import { Text } from '@/common/components/Text';
import { Toast, ToastProps } from '@/common/components/Toast';
import { useToast } from '@/common/hooks/useToast';

import { GoogleFormButton } from './_components/GoogleFormButton';
import { LogoutBar } from './_components/LogoutBar';
import { UserInfo } from './_components/UserInfo';

const MyPage = () => {
const [toastData, setToastData] = useState<ToastProps | null>(null);
const router = useRouter();
const { getSavedToastInfo, clearSavedToast } = useToast();
useEffect(() => {
setToastData(getSavedToastInfo());
clearSavedToast();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<div className="h-full">
<div>
{toastData && (
<Toast
isShow={toastData.isShow}
type={toastData.type}
direction={toastData.direction}
title={toastData.title}
/>
)}
<UserInfo />
<div className="h-40px" />
<LogoutBar />
<div className="h-56px" />
Expand All @@ -47,17 +23,7 @@ const MyPage = () => {
height={160}
alt="로켓 이미지"
/>
<Button
className="w-full"
size="L"
typo="subheadingBold"
backgroundColor="primaryDefault"
onClick={() => {
router.push(GOOGLE_FORM_URL);
}}
>
이런 퀴즈가 있었으면 좋겠어요
</Button>
<GoogleFormButton />
</div>
</div>
);
Expand Down
3 changes: 3 additions & 0 deletions src/common/utils/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export const authToken = {

export const redirectToLoginPage = () => {
const isDev = process.env.NODE_ENV === 'development';
if (typeof window === 'undefined') {
return;
}
Comment on lines +95 to +97
Copy link
Collaborator

Choose a reason for hiding this comment

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

redirectToLoginPage함수가 혹시나 서버 컴포넌트에서 호출될까 염려하여 얼리리턴 해준건가요?
ssr대응이라는게 어떤 문제가 있어서 추가하게 되었는지 궁금합니다..!

Copy link
Collaborator

Choose a reason for hiding this comment

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

아 실행 시켜보니 window를 참조하는 과정에서 에러가 발생하는군요

Copy link
Member Author

Choose a reason for hiding this comment

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

@dengoyoon 네네 맞아요!! 서버에서 렌더 될 때에는 window 참조를 못해서 서버 렌더되는 경우 아예 리턴 시켜서 에러 발생을 막기 위한 코드였습니다


window.location.href = isDev
? 'http://localhost:3000/toks-main'
Expand Down