Skip to content

Commit

Permalink
Merge pull request #226 from feedoong/fix/axios
Browse files Browse the repository at this point in the history
refactor: 모든 API 호출 로직이 codegen을 통하도록 수정함
  • Loading branch information
saengmotmi authored Jul 31, 2024
2 parents 6356c8d + 9a2e983 commit 9526f48
Show file tree
Hide file tree
Showing 55 changed files with 467 additions and 449 deletions.
46 changes: 46 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@emotion/is-prop-valid": "^1.2.2",
"@floating-ui/react-dom": "^1.0.0",
"@floating-ui/react-dom-interactions": "^0.10.2",
"@suspensive/react": "^2.10.0",
"@tanstack/react-query": "^5.50.1",
"@tanstack/react-query-devtools": "^5.32.1",
"@toss/react": "^1.3.6",
Expand Down
70 changes: 21 additions & 49 deletions apps/next-app/src/app/(hasGNB)/_components/Nav/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,32 @@
import React, { forwardRef } from 'react'
import { cookies } from 'next/headers'
'use client'
import { ErrorBoundary } from '@suspensive/react'
import { useRouter } from 'next/navigation'
import { forwardRef, Suspense } from 'react'

import ProfilePopover from 'components/common/Layout/Nav/ProfilePopover'
import { getApiEndpoint } from 'envs'
import * as S from 'components/common/Layout/Nav/Nav.style'
import { GoToSignUpButton } from './GoToSignUpButton'
import { Profile } from 'components/common/Layout/Nav/Profile'
import { ROUTE } from 'constants/route'
import { LogoButton } from './LogoButton'

async function getUserProfile() {
const cookieStore = cookies()
const accessToken = cookieStore.get('accessToken')
if (!accessToken) {
return null
}

const res = await fetch(`${getApiEndpoint()}/users/me`, {
headers: {
Authorization: `Bearer ${accessToken.value}`,
},
})
// The return value is *not* serialized
// You can return Date, Map, Set, etc.

if (res.status !== 200) {
// This will activate the closest `error.js` Error Boundary
throw new Error('Failed to fetch data')
}

return res.json()
}

const Nav = forwardRef<HTMLDivElement>(async function Nav(props, ref) {
const userProfile = await getUserProfile()
// NOTE: 서버 컴포넌트로 만들면 클라 측에서 갱신이 안됨
// app router용
const Nav = forwardRef<HTMLDivElement>(function Nav(props, ref) {
const router = useRouter()

return (
<S.TopNavContainer ref={ref}>
<LogoButton />

{userProfile?.name ? (
<ProfilePopover>
<S.MyPageButton>
<S.UserName>{`${userProfile.name}님, 안녕하세요!`}</S.UserName>
{userProfile.profileImageUrl && (
<S.UserImage
width={32}
height={32}
alt="프로필 사진"
src={userProfile.profileImageUrl}
priority
/>
)}
</S.MyPageButton>
</ProfilePopover>
) : (
<GoToSignUpButton />
)}
<ErrorBoundary
fallback={
<S.GoToSignUpButton onClick={() => router.push(ROUTE.SIGN_UP)}>
피둥 시작하기
</S.GoToSignUpButton>
}
>
<Suspense>
<Profile />
</Suspense>
</ErrorBoundary>
</S.TopNavContainer>
)
})
Expand Down
20 changes: 6 additions & 14 deletions apps/next-app/src/app/(hasGNB)/feed/me/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,15 @@ import type { NextPage } from 'next'
import { cookies } from 'next/headers'
import { Suspense } from 'react'

import { itemQueries } from 'entities/item/api'
import MyFeed from 'views/myFeed'
import { SkeletonPostType } from 'components/common/Skeleton'
import { getQueryClient } from 'core/getQueryClient'
import { feedoongApi } from 'services/api'
import { setAuthorizationHeader } from 'features/auth/token'
import { itemQueries } from 'entities/item/api'
import { checkLoggedIn } from 'shared/utils/checkLoggedIn'
import { SkeletonPostType } from 'components/common/Skeleton'

const FeedMePage: NextPage = () => {
const api = feedoongApi()
const cookieStore = cookies()
const accessToken = `${cookieStore.get('accessToken')?.value}`

setAuthorizationHeader(api, accessToken, { type: 'Bearer' })
import MyFeed from 'views/myFeed'

const FeedMePage: NextPage = async () => {
const queryClient = getQueryClient()
void queryClient.prefetchInfiniteQuery(itemQueries.list(api))
await queryClient.prefetchInfiniteQuery(itemQueries.list())

return (
<HydrationBoundary state={dehydrate(queryClient)}>
Expand All @@ -28,7 +20,7 @@ const FeedMePage: NextPage = () => {
<SkeletonPostType key={index} />
))}
>
<MyFeed isLoggedIn={checkLoggedIn(cookieStore)} />
<MyFeed isLoggedIn={checkLoggedIn(cookies())} />
</Suspense>
</HydrationBoundary>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const Container = styled.div`
gap: 12px;
border-radius: 20px;
border-bottom-left-radius: 0px;
margin-bottom: 20px;
`

export const Title = styled.h2`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const PrivatePostType = ({ item }: { item: PrivatePost }) => {
src={item.isLiked ? Icons.Bookmark : Icons.BookmarkDeactive}
width={16}
height={16}
onClick={() => handleLike(String(item.id))}
onClick={() => handleLike(item.id)}
priority
/>
</CardActions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
import produce from 'immer'

import { CACHE_KEYS } from 'services/cacheKeys'
import { submitViewedPost } from 'services/feeds'
import { viewItemUsingPOST } from 'services/types/_generated/item'
import type { Feed, SubmitViewedPost } from 'types/feeds'
import { mergeObjectsByMutate } from 'utils/common'

Expand All @@ -17,7 +17,7 @@ const useReadPost = (item: { id: number }) => {

const { mutate: handleRead } = useMutation({
mutationKey: CACHE_KEYS.viewItem(item.id),
mutationFn: submitViewedPost,
mutationFn: viewItemUsingPOST,
onSuccess: (data, variables) => {
client.setQueryData<PrevDataType>(CACHE_KEYS.feeds, (prev) => {
if (!prev) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
import Toast from 'components/common/Toast'
import { itemQueries } from 'entities/item/api'
import { CACHE_KEYS } from 'services/cacheKeys'
import { likePost, unlikePost } from 'services/feeds'
import {
likeUsingPOST,
unlikeUsingDELETE,
} from 'services/types/_generated/like'

// TODO: 추후에 useToggleLike 자체를 재작성해야 함. 임시로 인자 타입 변경
const useToggleLike = (item: { id: number; isLiked: boolean }) => {
const client = useQueryClient()

const { mutate: handleLike } = useMutation({
mutationKey: CACHE_KEYS.likePost(item.id),
mutationFn: !item.isLiked ? likePost : unlikePost,
mutationFn: !item.isLiked ? likeUsingPOST : unlikeUsingDELETE,
onSuccess: async (data) => {
client.invalidateQueries(itemQueries.list())
client.invalidateQueries({ queryKey: CACHE_KEYS.feeds })
Expand Down
42 changes: 16 additions & 26 deletions apps/next-app/src/components/common/Layout/Nav/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,36 @@
'use client'

import React, { forwardRef } from 'react'
import { ErrorBoundary, Suspense } from '@suspensive/react'
import { useRouter } from 'next/navigation'
import { forwardRef } from 'react'

import { useGetUserProfile } from 'features/user/userProfile'
import ProfilePopover from './ProfilePopover'
import { ROUTE } from 'constants/route'
import LogoDesktopNoBackground from 'components/common/LogoDesktop'
import { ROUTE } from 'constants/route'
import { Profile } from './Profile'

import * as S from './Nav.style'

// pages router용
const Nav = forwardRef<HTMLDivElement>(function TopNavBar(props, ref) {
const router = useRouter()
const { data: userProfile } = useGetUserProfile()

return (
<S.TopNavContainer ref={ref}>
<S.LogoButton onClick={() => router.push('/')}>
<LogoDesktopNoBackground color={'var(--color-black)'} />
<S.Feedoong>Feedoong</S.Feedoong>
</S.LogoButton>

{userProfile?.name ? (
<ProfilePopover>
<S.MyPageButton>
<S.UserName>{`${userProfile.name}님, 안녕하세요!`}</S.UserName>
{userProfile.profileImageUrl && (
<S.UserImage
width={32}
height={32}
alt="프로필 사진"
src={userProfile.profileImageUrl}
priority
/>
)}
</S.MyPageButton>
</ProfilePopover>
) : (
<S.GoToSignUpButton onClick={() => router.push(ROUTE.SIGN_UP)}>
피둥 시작하기
</S.GoToSignUpButton>
)}
<ErrorBoundary
fallback={
<S.GoToSignUpButton onClick={() => router.push(ROUTE.SIGN_UP)}>
피둥 시작하기
</S.GoToSignUpButton>
}
>
<Suspense>
<Profile />
</Suspense>
</ErrorBoundary>
</S.TopNavContainer>
)
})
Expand Down
34 changes: 34 additions & 0 deletions apps/next-app/src/components/common/Layout/Nav/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client'
import { useSuspenseQuery } from '@tanstack/react-query'

import { CACHE_KEYS } from 'services/cacheKeys'
import { getUserInfoUsingGET } from 'services/types/_generated/user'
import ProfilePopover from './ProfilePopover'

import * as S from './Nav.style'

export const Profile = () => {
const { data: userProfile } = useSuspenseQuery({
queryKey: CACHE_KEYS.me,
queryFn: getUserInfoUsingGET,
retry: false,
meta: { ignoreToast: true },
})

return (
<ProfilePopover>
<S.MyPageButton>
<S.UserName>{`${userProfile.name}님, 안녕하세요!`}</S.UserName>
{userProfile.profileImageUrl && (
<S.UserImage
width={32}
height={32}
alt="프로필 사진"
src={userProfile.profileImageUrl}
priority
/>
)}
</S.MyPageButton>
</ProfilePopover>
)
}
3 changes: 2 additions & 1 deletion apps/next-app/src/components/common/Providers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const Providers = ({ pageProps, children }: Props) => {
},
},
queryCache: new QueryCache({
onError: (err: unknown) => globalQueryErrorHandler(err, queryClient),
onError: (err: unknown, query) =>
globalQueryErrorHandler(err, query, queryClient),
}),
})
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useRouter } from 'next/router'
import { useState } from 'react'
import Skeleton from 'react-loading-skeleton'

// import * as S from 'components/views/MyPost/PostContainer.style'

import Flex from 'components/common/Flex'
import FeedItem from 'components/common/FeedItem/FeedItem'
import { getChannel } from 'services/feeds'
import { CACHE_KEYS } from 'services/cacheKeys'
import Flex from 'components/common/Flex'
import LogoIcon from 'components/common/LogoIcon'
import PageContainer from 'components/common/PageContainer'
import Paging from 'components/common/Paging'
import { SkeletonPostType } from 'components/common/Skeleton'
import { ITEMS_PER_PAGE } from 'constants/pagination'
import { CACHE_KEYS } from 'services/cacheKeys'
import { getItemsOfSubscribedChannelUsingGET } from 'services/types/_generated/item'
import { getWellKnownChannelImg } from 'utils'
import PageContainer from 'components/common/PageContainer'
import LogoIcon from 'components/common/LogoIcon'
import ChannelSubscription from './ChannalSubscription'

import * as S from './ChannelDetailContainer.style'
Expand All @@ -26,7 +26,11 @@ function PostContainer() {
const [currentPage, setCurrentPage] = useState(1)
const { data, isLoading } = useQuery({
queryKey: [CACHE_KEYS.likedPosts, { page: currentPage, channel: id }],
queryFn: () => getChannel(id, currentPage),
queryFn: () =>
getItemsOfSubscribedChannelUsingGET(Number(id), {
page: currentPage,
size: 10,
}),
enabled: !!id,
})

Expand Down
2 changes: 2 additions & 0 deletions apps/next-app/src/components/views/Feeds/FeedsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client'

import { useRouter } from 'next/router'
import { SwitchCase } from '@toss/react'

Expand Down
Loading

0 comments on commit 9526f48

Please sign in to comment.