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

[오영택] sprint 5,9 #704

Open
wants to merge 62 commits into
base: main
Choose a base branch
from

Conversation

Programmeryeongtaek
Copy link
Collaborator

@Programmeryeongtaek Programmeryeongtaek commented Jun 14, 2024

요구사항

기본

<미션 9>

  • 자유 게시판 페이지 주소는 “/boards” 입니다.
  • 전체 게시글에서 드롭 다운으로 “최신 순” 또는 “좋아요 순”을 선택해서 정렬을 할 수 있습니다.
  • 게시글 목록 조회 api를 사용하여 베스트 게시글, 게시글을 구현합니다.
  • 게시글 title에 검색어가 일부 포함되면 검색이 됩니다.
  • 베스트 상품 기준(정렬 : like가 높은 순)

<미션 5> 넥스트로 구현

  • 전체 상품에서 드롭 다운으로 “최신 순” 또는 “좋아요 순”을 선택해서 정렬을 할 수 있습니다
  • [] ‘상품 등록하기’ 버튼을 누르면 “/additem” 로 이동합니다 ( 빈 페이지 )
  • 카드 데이터는 제공된 백엔드 API 페이지의 GET 메소드인 “/products”를 사용해주세요
  • 미디어 쿼리를 사용하여 반응형 view 마다 물품 개수를 다르게 보여줍니다 (서버로 요청하는 값은 동일)
  • 베스트 상품 (Desk 4, Tablet 2, Mobile 1)
  • 전체 상품 (Desk 12, Table 6, Mobile 4)
  • 중고마켓 페이지 주소는 “/items” 입니다.
  • 페이지 주소가 “/items” 일때 상단네비게이션바의 “중고마켓" 버튼의 색상은 “3692FF”입니다.
  • 상단 네비게이션 바는 이전 미션에서 구현한 랜딩 페이지와 동일한 스타일로 만들어 주세요.
  • 베스트 상품 기준(favorite가 가장 높은 상품 4가지)

심화

<미션 9>

  • 반응형으로 보여지는 베스트 게시판 개수를 다르게 설정할 때 서버에 보내는 pageSize값을 적절하게 설정합니다.
  • [] next의 data prefetch 기능을 사용해봅니다.

<미션 5>

  • [] 페이지 네이션 기능을 구현합니다.
  • 반응형으로 보여지는 물품들의 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다.

주요 변경사항

스크린샷

image

멘토에게

-tailwind 동적 CSS 구현방법을 잘 모르겠습니다...

  • 공통 컴포넌트의 재사용성을 구현하는 게 익숙하지 않습니다.
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.
  • 이전 미션들과 함께 계속해서 구현에 힘쓰겠습니다!

@Programmeryeongtaek Programmeryeongtaek changed the title Next.js 오영택 sprint11 [오영택] sprint 5,9 Jun 14, 2024
@Programmeryeongtaek Programmeryeongtaek added 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. 미완성🫠 죄송합니다.. labels Jun 14, 2024
})

try {
const res = await fetch(
Copy link
Collaborator

Choose a reason for hiding this comment

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

공통 api 함수가 하나 있으면 좋겠네요.

아래 baseApi 함수를 확인해주시면 됩니다.

type BaseApiMethods = "get" | "post" | "put" | "patch" | "delete";
type BaseApiCommonArgs = {
  url: URL;
  headers: RequestInit["headers"];
};

interface BaseApiNonBodyArgs extends BaseApiCommonArgs {
  method: "get" | "delete";
}

interface BaseApiWithBodyArgs extends BaseApiCommonArgs {
  method: "post" | "put" | "patch";
  body: RequestInit["body"];
}

type BaseApiArgs<T extends BaseApiMethods> = T extends "get"
  ? BaseApiNonBodyArgs
  : BaseApiWithBodyArgs;

type BaseApiArgsType = BaseApiNonBodyArgs | BaseApiWithBodyArgs;
type BaseApiFunc = <T extends BaseApiArgsType["method"]>(
  data: BaseApiArgs<T>
) => Promise<Response>;

const API_BASE_URL = "https://panda-market-api.vercel.app";

export const baseApi: BaseApiFunc = async ({ url, ...args }) => {
  try {
       const timeout = AbortSignal.timeout(5000); // timeout 5초
       return await fetch(`${API_BASE_URL}/${url}`, { ...args, signal: timeout });
  }
  catch(err) {
    // 실패했을 때 공통적으로 return 해줘야 할 응답값
  }
};


const viewportWidth = useViewport();

useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

useEffect는 react의 여러 라이프사이클을 핸들링 할 수 있는 훅입니다.

그래서 내부에서 추가적으로 호출해줘야되는 함수들이 늘어날 수 있기 때문에, 함수의 구현부(fetchBestArticles)는 useEffect 외부로 빼주시면 좋습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

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

전반적으로 기본적인 기능 구현사항이라 크게 커멘트를 남길 필요는 없을 듯 합니다.

그리고 현재 각 컴포넌트에서 api 호출 후, 응답 데이터를 state로 관리하여 ui 렌더링 시키는 구조가 많은 데,
setLoading(true) -> api response -> setLoading(false) -> setData 이런 반복적인 코드가 보이네요.

type UseApiArgs {
   // .....
}

// useApi 내부에서 실제 api 콜을 하는 함수
type Fetcher {
   // ....
}
const useApi = <T>(fetcher: Fetcher) => {
  const [data, setData] = useState<T>();
  const [isLoading, setIsLoading] = useState(false); 
  const [error, setError] = useState(); 
  
  const trigger = async () => {
     try{
        setIsLoading(true);
        const result = await fetcher();
        setIsLoading(false;
        setData(result)
     }
     catch(err) {
        setError(err);
     }
  } 

  return {
    data, isLoading, error, trigger
  }

} 

// ./page or ./component
const fetcher = () => {
    return fetch("", {});
}
const DummyComponent = () => {
    const {data, isLoading, error, trigger} = useApi(fetcher);

    return (
        <>
        {isLoading && <Loading />}
        {!isLoading && <div>{JSON.stringify(data)}</div>
        </>
     )
} 

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