-
Notifications
You must be signed in to change notification settings - Fork 40
[김승준] sprint9 #311
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
[김승준] sprint9 #311
The head ref may contain hidden characters: "Next-\uAE40\uC2B9\uC900-sprint9"
Conversation
- Split Article component into BestArticle and NormalArticle for better separation of concerns - Move common props management to parent component - Improve image resource handling - Pass likeIcon from parent component - Keep bestBadge within BestArticle component BREAKING CHANG: Internal structure of Article component has been modified
…/ setKeyword state가 input작성 후 500ms가 지나면 setKeyword가 실행되도록 수정
arthurkimdev
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
승준님 과제 제출하시느라 수고하셨습니다~ 👍
| const apiGetArticles = async ( | ||
| params: ArticleParams | ||
| ): Promise<ArticleResponse> => { | ||
| try { | ||
| const { data } = await axios.get<ArticleResponse>( | ||
| `${baseUrl}/articles?${createQueryParams(params)}` | ||
| ); | ||
| return data; | ||
| } catch (error) { | ||
| const message = axios.isAxiosError(error) | ||
| ? error.response?.data?.message ?? | ||
| "error occurred & server error message is missing" | ||
| : "An unexpected error occurred(not axios error)"; | ||
| throw new Error(message); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네이밍에 정답은 없지만, 현업 사례로 기준을 잡고 말씀드리면 API를 요청하는 부분은 fetchOOOO 통일하곤 해요. 즉 fetchArticles 가 되겠습니다. 또한 아래처럼 도메인 중심 네이밍 방법도 있는데요. 선택하셔서 수정하면 지금 보다 더 좋은 네이밍과 유연한 설계가 될 것 같아요. 😸
const articles = {
list: () => axios.get('/articles'),
detail: (id: string) => axios.get(`/articles/${id}`),
create: (data: ArticleData) => axios.post('/articles', data),
update: (id: string, data: ArticleData) => axios.put(`/articles/${id}`, data),
delete: (id: string) => axios.delete(`/articles/${id}`)
};
| export const useArticles = (params: ArticleParams) => | ||
| useQuery({ | ||
| queryKey: ["articles", params], | ||
| queryFn: () => apiGetArticles(params), | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정답은 없지만 이러한 쿼리 요청 함수들은 fetch 파일에서 전부 관리하지 않고, hooks/queries 에 별도로 정리하는 방식도 있어요.
ㄴ api
ㄴ fetchArticles.ts
ㄴ hooks
ㄴ queries
ㄴ useArticles.ts
| const containerStyles = | ||
| "flex flex-col mx-auto w-[343px] tablet:w-[696px] pc:w-[1200px]"; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런 클래스명이 담긴 집함체들은 tailwind를 사용할 때, global.css 파일을 하나 만들어서 아래처럼 정의 후 사용할 수 있어요.
@layer components {
. container-styles {
@apply flex flex-col mx-auto w-[343px] tablet:w-[696px] pc:w-[1200px]
}
export default function BoardsPage() {
return (
<div className={container-styles}>
<BestSection />
<NormalSection />
</div>
);
}
```
|
|
||
| return ( | ||
| <section className="mb-6 pc:mb-10 w-full"> | ||
| <h1 className="text-[20px] font-[700] mb-4 tablet:mb-6">베스트 게시글</h1> | ||
| <div className="flex gap-0 tablet:gap-4 pc:gap-6 w-full"> | ||
| {isLoading ? ( | ||
| <BestArticleSkeletons count={pageSize} /> | ||
| ) : ( | ||
| <BestArticleList articles={data?.list ?? []} /> | ||
| )} | ||
| </div> | ||
| </section> | ||
| ); | ||
| }; | ||
|
|
||
| export default BestSection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 부분은 Suspense와 ErrorBoundary를 사용하여 선언적 처리를 해볼 수 있어요. 즉 지금처럼
if (error) {
return <div>process of fetching articles failed</div>;
}
if (loading) {
...
}
위와 같은 코드를 선언적으로 대체해주는 방법이예요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";
...
const BestSection = () => {
return (
<section className="mb-6 pc:mb-10 w-full">
<h1 className="text-[20px] font-[700] mb-4 tablet:mb-6">베스트 게시글</h1>
<ErrorBoundary FallbackComponent={ErrorFallback}>
<Suspense fallback={<BestArticleSkeleton />}>
<BestArticleContent />
</Suspense>
</ErrorBoundary>
</section>
);
};
export default BestSection;
| interface NormalArticleProps extends Omit<Article, "image"> { | ||
| imageUrl: string; | ||
| likeIcon: string; | ||
| isLoading: boolean; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Omit 사용 굳! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그 외로 많이 사용하는 Pick, Partial, Required 도 사용해보세요~
| return ( | ||
| <DropdownMenu> | ||
| <DropdownMenuTrigger | ||
| className="flex items-center justify-center gap-2 h-[42px] rounded-[12px] border bg-white hover:bg-gray-50 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정말 자주 사용하는 flex items-center justify-center 이런 것들은 global.css 에 아래처럼 클래스네임을 직접 커스텀하게 추가해서 사용해보세요. 예를들어 flex-center로 작명 후 조금 더 빠르게 스타일을 선언할 수 있습니다.
.flex-center {
@apply flex items-center justify-center
}
이 후, 아래처럼 적용해볼 수 있겠어요.
className="flex-center gap-2 h-[42px] rounded-[12px] border bg-white hover:bg-gray-50"
요구사항
기본
/boards입니다.심화
pageSize값을 적절히 설정했습니다.주요 변경사항
/boards) 추가스크린샷
멘토에게