상세 컨텐츠

본문 제목

PRODUCT ID별 상품 가져오기 / 코멘트 가져오기 / 코드 리뷰

성장일지

by 모모87 2024. 7. 9. 00:18

본문

 

 

 

스프린트 일곱번째 미션이다.

점점 컴포넌트에 대한 이해도가 올라간다.

useHook

useMemo

useCallback을 통한 최적화를 계속 연습해야지.

 

근데 갈수록 의욕이 상실된다...

 

이유는..

분위가 다들 열심히 하는 분위기 되면

나도 따라가는데

뭔가 다들 하기 싫어하는 분위기?같아서

솔직히 하기 싫다.

 

나는 주부에 솔직히 제일 당장 취업이 아쉬운 것도 아닌데

나만 용쓰는 느낌인 것 같아서 

... 힘이 안난다.

 

내가 힘이 너무 들어갔나????

 

취업해도 사람들과 관계가 좋을까...

전에도 개발직군 사람들과 종종 트러블이 있었기 때문에

일 자체에 근본적인 생각이 자꾸 나를 힘들게 한다.

 

일반 회사는 솔직히 나이가 걸림돌이 될 것 같고

상주 단기 프리랜서를 목표로 공부하긴 하지만

의욕이 많이 도태되어 있다.

그래도 이렇게 코드 리뷰 남기면서

나 자신과의 싸움을 해본다.

 

마지막 버킷 리스트인데 무조건 달려보자.. 리마인드 세팅..

 

 

 

기본 요구사항

  • Github에 PR(Pull Request)을 만들어서 미션을 제출합니다.
  • 피그마 디자인에 맞게 페이지를 만들어 주세요.
  • React를 사용합니다

체크리스트 [기본]

상품 상세

  • response 로 받은 아래의 데이터로 화면을 구현합니다.
  • 상품 상세 페이지 주소는 “/items/{productId}” 입니다.

=>  favoriteCount : 하트 개수

=>  images : 상품 이미지

=>  tags : 상품태그

=>  name : 상품 이름

=>  description : 상품 설명

  • 목록으로 돌아가기 버튼을 클릭하면 중고마켓 페이지 주소인 “/items” 으로 이동합니다

상품 문의 댓글

  • response 로 받은 아래의 데이터로 화면을 구현합니다
  • 문의하기에 내용을 입력하면 등록 버튼의 색상은 “3692FF”로 변합니다.

=>  image : 작성자 이미지

=>  nickname : 작성자 닉네임

=>  content : 작성자가 남긴 문구

=>  description : 상품 설명

=>  updatedAt : 문의글 마지막 업데이트 시간


 

1. form 내부 컴포넌트화

<form onSubmit={handleSubmit} onKeyDown={handleFormKeyDown}>
    <div className="section-header">
      <h2 className="title">상품 등록하기</h2>
      <button className="btn-primary btn-sm" type="submit" disabled={!isFormValid}>
        등록
      </button>
    </div>
    <FileInput label="상품이미지" name="imgFile" value={values.imgFile} onChange={handleChange} />
    <TextInput
      label="상품명"
      name="product"
      value={values.product}
      onChange={handleInputChange}
      placeholder="상품명을 입력해주세요"
    />
    <TextArea
      label="상품 소개"
      name="content"
      value={values.content}
      onChange={handleInputChange}
      placeholder="상품 소개를 입력해주세요"
      rows="10"
    />
    <NumberInput
      label="판매가격"
      name="price"
      value={values.price}
      onChange={handleInputChange}
      placeholder="판매 가격을 입력해주세요"
    />
    <TagInput
      label="태그"
      name="tag"
      onTagListChange={handleTagListChange}
      placeholder="태그를 입력 후 Enter를 눌러 추가하세요"
    />
</form>

 

원래 input 그룹으로 묶어서 lable과 input으로 되었는데 전부 컴포넌트로 분리 시켰다. 


 

2. api주소 상수화 중복개선

export async function getProducts(params = {}) {
  const query = new URLSearchParams(params).toString();

  try {
    const response = await fetch(`${API_BASE_URL}/products?${query}`);
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    const body = await response.json();
    return body;
  } catch (error) {
    console.error('Failed to fetch products:', error);
    throw error;
  }
}

export async function getProductById(productId) {
  try {
    const response = await fetch(`${API_BASE_URL}/products/${productId}`);
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    const body = await response.json();
    return body;
  } catch (error) {
    console.error('Failed to fetch product:', error);
    throw error;
  }
}

 

자주쓰는 api 주소를 상수화 하여 코드를 줄였다.


 

3.useHook으로 중복된  useEffect 처리/ 코드 단순화

import { useState, useEffect } from 'react';
import { getProducts } from '../services/api';

const useProducts = (initialOrderBy, getPageSize) => {
  const [orderBy, setOrderBy] = useState(initialOrderBy);
  const [products, setProducts] = useState([]);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(getPageSize());
  const [totalPageNum, setTotalPageNum] = useState(0);
  const [loading, setLoading] = useState(false);

  const handleLoad = async ({ orderBy, page, pageSize }) => {
    setLoading(true);
    try {
      const products = await getProducts({ orderBy, page, pageSize });
      setProducts(products.list);
      setTotalPageNum(Math.ceil(products.totalCount / pageSize));
    } catch (error) {
      console.error('Failed to load products:', error);
      setProducts([]);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    const handleResize = () => {
      setPageSize(getPageSize());
    };
    window.addEventListener('resize', handleResize);

    handleLoad({ orderBy, page, pageSize });

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, [orderBy, page, pageSize]);

  return {
    orderBy,
    setOrderBy,
    products,
    page,
    setPage,
    pageSize,
    totalPageNum,
    loading,
  };
};

export default useProducts;

 

BestItem이랑 AllItem 두군데에서 불러오는 api를 하나의 useProductList라는 훅을 통해 코드량을 줄이고

가독성을 올려준다.


 

 

회고

 

미션 7을 마치면서 조금은 state 사용과 컴포넌트 사용에 자신감이 붙는다.

 

반응형

관련글 더보기