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

[오정민] sprint12 #326

Merged

Conversation

ojm51
Copy link
Collaborator

@ojm51 ojm51 commented Sep 27, 2024

요구사항

  • Github에 PR(Pull Request)을 만들어서 미션을 제출합니다.
  • 피그마 디자인에 맞게 페이지를 만들어 주세요.
  • React, Typescript를 사용합니다.
  • api 요청에 TanStack React Query를 활용해 주세요.
  • 모든 POST, PUT 요청에는 엑세스 토큰이 필요합니다.

기본

중고마켓

  • ‘상품 등록하기’ 버튼을 누르면 “/additem” 로 이동합니다.
  • 각 상품 클릭 시 상품 상세 페이지로 이동합니다.
  • 상품 상세 페이지 주소는 “/items/{productId}” 입니다.

상품 상세

  • 내가 등록한 상품일 경우 상품 수정, 삭제가 가능합니다.
  • 문의하기 input창에 값을 입력 후 ‘등록’ 버튼을 누르면 댓글이 등록됩니다.
  • 내가 등록한 댓글은 수정, 삭제가 가능합니다.

상품 등록

  • 이미지를 제외하고 input 에 모든 값을 입력하면 ‘등록' 버튼이 활성화 됩니다.
  • 활성화된 ‘등록' 버튼을 누르면 상품 등록이 완료됩니다.
  • 등록이 완료되면 해당 상품 상세 페이지로 이동합니다.

주요 변경사항

  • 상품 페이지 추가
  • 상품 상세 페이지 추가
  • 게시글/제품 관련 api 파일 생성
  • axios interceptor 생성
  • 일부 타입명/변수명 수정

스크린샷

멘토에게

  • 인터셉터로 엑세스 토큰 만료 시 리프레시 토큰을 사용하여 갱신하는 코드를 구현해보았는데 동작하지 않는 것 같습니다..!(lib/instance.ts)

  • 상품을 클릭하여 상세 페이지로 들어가면 아래와 같은 오류가 뜹니다.

    • 제가 생각한 과정은
    • 상품을 클릭하면 -> 401 Unauthorized 에러가 발생하기 때문에 -> 리프레시 토큰으로 새로운 엑세스 토큰을 발급받아 -> 상품 상세 정보를 불러오는 것인데
    • 리프레시 요청은 404 Not Found 에러가 뜹니다
      image
      image
      image
  • 마지막 주에 추가로 구현하여 올리겠습니다.

  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

@ojm51 ojm51 requested a review from 201steve September 27, 2024 06:53
@ojm51 ojm51 added 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. 미완성🫠 죄송합니다.. labels Sep 27, 2024
@201steve
Copy link
Collaborator

반가워요 정민님 :-) PR 본문에 어떤걸 개발하셨는지 적어주시면 더욱 좋을것같네요! 업데이트 부탁드립니닷!

@ojm51 ojm51 self-assigned this Sep 30, 2024
@201steve
Copy link
Collaborator

인터셉터로 엑세스 토큰 만료 시 리프레시 토큰을 사용하여 갱신하는 코드를 구현해보았는데 동작하지 않는 것 같습니다..!(lib/instance.ts)

상품을 클릭하여 상세 페이지로 들어가면 아래와 같은 오류가 뜹니다.

제가 생각한 과정은
상품을 클릭하면 -> 401 Unauthorized 에러가 발생하기 때문에 -> 리프레시 토큰으로 새로운 엑세스 토큰을 발급받아 -> 상품 상세 정보를 불러오는 것인데
리프레시 요청은 404 Not Found 에러가 뜹니다

  • 404가 나왔다 하면, 일단 내가 오타가 있나? 아니면 api url에 맞게 요청하고있나? 의심부터 해보는게 해결하는 가장 빠른 길입니다.
  • auth/refresh로 요청하고 계신데, auth/refresh-token 으로 요청 해야 하죠
  • 스크린샷 2024-09-30 오후 11 34 14

Copy link
Collaborator

@201steve 201steve left a comment

Choose a reason for hiding this comment

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

수고 많으셨습니닷!!!

Comment on lines +1 to +7
export interface fetchArticleByIdParams {
articleId: string;
}

export interface fetchArticleCommentsByIdParams {
articleId: string;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
export interface fetchArticleByIdParams {
articleId: string;
}
export interface fetchArticleCommentsByIdParams {
articleId: string;
}
export type ArticleId = {
articleId: string;
};
export type fetchArticleByIdParams = ArticleId;
export type fetchArticleCommentsByIdParams = ArticleId;

타입도 변수처럼 재사용이 가능해서 이런 방법도 있습니다.

아니면

export type ArticleId = {
  articleId: string;
};

타입 하나만 만들어서 써도 되긴 합니다 :-)


export async function fetchProductDataById(productId: string) {
const response = await instance.get(API_PATH.productsWithId(productId));
console.log(response);
Copy link
Collaborator

Choose a reason for hiding this comment

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

commit 전에 console.log가 남아있는지 확인 해주시면 좋을것같네여 :-)

}
}
getProductComment();
}, []);
Copy link
Collaborator

Choose a reason for hiding this comment

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

productId가 바뀔때마다 업데이트가 필요할것같은데,
의존성 배열은 빈 배열이라 한번만 업데이트하고 다시 실행되지 않을것 같아요 🤔

getProductDetail();

async function getProductComment() {
const LIMIT = 10;
Copy link
Collaborator

Choose a reason for hiding this comment

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

이런 상수는 컴포넌트가 업데이트 될 때마다 생성되지않아도 돼서, 컴포넌트 밖에서 관리 해도 될것같아요

const LIMIT = 10;

function ProductDetailPage() {

Comment on lines +18 to +43
const [productDetails, setProductDetails] = useState<ProductTypes | null>(
null,
);
const [productComments, setProductComments] = useState<CommentTypes[]>([]);

const router = useRouter();
const { productId } = router.query;

useEffect(() => {
async function getProductDetail() {
if (typeof productId === "string") {
const data = await fetchProductDataById(productId);
setProductDetails(data);
}
}
getProductDetail();

async function getProductComment() {
const LIMIT = 10;
if (typeof productId === "string") {
const data = await fetchProductComment(productId, LIMIT);
setProductComments(data);
}
}
getProductComment();
}, []);
Copy link
Collaborator

Choose a reason for hiding this comment

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

const router = useRouter();
const { productId } = router.query;

이 코드만 제외하고, 나머지 코드는 커스텀 훅으로 추출해서 UI 렌더하는 컴포넌트랑, 데이터 받아오는 커스텀 훅이랑 관심사를 분리시킬 수 있을 것 같아요!

Comment on lines 61 to 67
const isFormCompleted = email && nickname && password && passwordConfirmation;
// TODO: ts-pattern 적용?
// const isFormCompleted = match({ email, nickname, password, passwordConfirmation })
// .with({email:String, nickname: String, password: String, passwordConfirmation: String }, () => true)
// .otherwise(() => false));
const isPasswordValid = password === passwordConfirmation;
const isButtonDisabled = !isFormCompleted || !isPasswordValid || isSubmitting;
Copy link
Collaborator

Choose a reason for hiding this comment

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

form 유효성 검사, form field마다 에러 및 완료 표시같은 기능이 제공되는
React-hook-form을 써보시는건 어떨까요??

Comment on lines +13 to +20
const sortedProducts = [...products].sort((a, b) => {
if (order === "createdAt") {
return (
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
}
return (b as any)[order] - (a as any)[order];
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
const sortedProducts = [...products].sort((a, b) => {
if (order === "createdAt") {
return (
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
}
return (b as any)[order] - (a as any)[order];
});
type SortOption = "createdAt" | "favoriteCount";
const sortProducts = (products: ProductTypes[], order: SortOption) => {
return [...products].sort((a, b) => {
if (order === "createdAt") {
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
}
return b[order as keyof ProductTypes] - a[order as keyof ProductTypes];
});
};
useEffect(() => {
const sortedProducts = sortProducts(products, order);
setShowedProducts(sortedProducts.slice(0, 10));
}, [order, products]);
  • useEffect 안에 있던 식을 함수로 추출하고, 추출한 함수를 useEffect에서 호출만 하는 방법도 될것같아요

@201steve 201steve merged commit 3fce3bb into codeit-bootcamp-frontend:Next-오정민 Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. 미완성🫠 죄송합니다..
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants