본문 바로가기

study/TIL

[TIL No.20] React Hooks

개요

오늘은 Redux를 배우기 전에 React에서 usestate만 가지고 상태관리를 해서 장바구니 기능 중 일부 기능이 구현되어있지않은 상황에서 기능을 몇 가지 추가해봤다.

 

상태관리가 무엇인지에 대해서 먼저 작성해야하지만... 그 내용은 아직 정리하기가 힘들어 리덕스를 배우고 적용해보면서 다뤄보도록 하고 오늘도 실습한 것 위주로 내가 배우고 익힌 포인트들을 정리해보도록 하자.

 

오늘 구현할 기능 요약

1️⃣ 장바구니에 선택항목 추가

2️⃣ 장바구니에 있는 상품개수 업데이트

3️⃣ 장바구니의 선택항목 삭제

 

글로는 최대한 깔끔하게 정리하도록 해볼텐데... 사실 과제를 하고 옆 그룹에 놀러갔다가 불완전한 기능구현을 발견하고 다시 수정하고 여러 번의 수정이 있었다..🥺

페이지 전환은 react-router-dom 을 이용해 Client Side Routing이 구현되어져 있었다. 전에 이용해봤던 <Router>, <Routes>, <Route>를 사용하여 라우팅 할 컴포넌트들을 구분짓고, Nav 내비게이션 바를 통해 <Link> 컴포넌트를 사용하여 현재 초기화면인 상품리스트 화면과 장바구니 화면 두 가지 경로로 라우팅 되게 설계되어있다.

 

#1. 라우팅 기능 추가 한 스푼

추가적으로 화면 상단 중앙에 Nav 안에 코드스테이츠 로고와 CMarket 글자를 클릭하는 경우 장바구니에서 상품페이지로 돌아오도록 해주었다.

<Link to="/">
<span id="title">
	<img id="logo" src="../logo.png" alt="logo" />
    <span id="name">CMarket</span>
</span>
</Link> // span #title을 링크 컴포넌트로 감싸주었다.

 

#2. 장바구니에 선택항목 추가

본격적으로 기능을 추가하기에 앞서,,, 이미 만들어지고 있는 어플리케이션에 만들던 사람이 급하게 퇴사하고 내가 신입으로서 기능을 추가하는 느낌이었다🧐

그래서 가장 중요했던 점이 컴포넌트들의 구조를 파악하는 것이었다.

 

이렇게 잘 정리해야한다...

 

나는 이렇게 잘 정리하지는 못했고, 상태가 어디에 몇 개가 있는지 처음에 파악하고, 각 item,cartitem,Nav 등등 여러 파일들이 있는데 html 구조가 머리에 안들어오면 코드를 읽기 매우 어려워하는 나 자신을 알기에 가장먼저 어떻게 DOM이 랜더링 되는지부터 파악하였다. 그렇게 차분하게 살펴보니 그림에서처럼 itemListContainer 안에 item이라는 컴포넌트가 여럿 나열되어있으며 ShoppingCart 하위에 CartItem과 OrderSummary 컴포넌트가 있어 각각의 화면을 구성하고 있었다.

나 같은 경우는 item과 CartItem이 어떻게 구성되어있는지 이벤트가 발생하면 타겟은 어디인지를 먼저 살피고 기능을 만들러 갔는데 덕분에 item 컴포넌트 속의 버튼에서 이벤트 핸들러에게 이벤트 객체와 아이템의 itemId 값을 넘겨주어서 이벤트 핸들링 함수에 Id를 두 번째 인자로 받아오는 과정에서 헤메지 않고 잘 작성할 수 있었다.

 

장바구니에 상품목록에서 선택된 item을 넣는 것은 cartItems라는 상태에 선택된 item을 넣어주면 업데이트 할 수 있다. cartItems 상태는 setcartItems를 호출해서 업데이트를 해주는 것이 가장 이상적인데 최종코드는 이렇게 작성되었다.

 

function setCart(itemId) {

  if(cartItems.filter(el => el.itemId === itemId).length === 1){
    
    setCartItems(cartItems.map(el => {
      if(el.itemId === itemId){
        el.quantity += 1;
        return el;
      } else {
        return el;
      }
    }))
  } else {
    setCartItems([...cartItems, { itemId, quantity:1 }]);
  }

 

이 코드를 app.js에 함수로 만들어서 itemListContainer로 넘겨주는 방식을 이용했다. 그런데, 이번에 과제에서 의도한 것은 setCartItems를 props로 넘겨주고 그것을 itemListContainer에 있는 이벤트 핸들러 함수에서 직접 사용하는 것이었다. 이하에 구현한 ShoppingCart에서는 해당 방식을 이용하였다. 따라서 두 가지 방식을 다 이용해 본 것인데, Redux를 아직 제대로 공부하지는 않았지만 별도의 파일에 app.js에 내가 함수를 만든 것처럼 상태관리를 하는 변수,함수를 전부 모아두고 필요한 컴포넌트에 뿌려주는 방식을 사용할 것 같았다.

위와 같이 함수를 만들어두고 props를 넘겨받아 이벤트 핸들러 함수는 그냥 setCart를 실행하도록 다음과 같이 작성해줬다.

const handleClick = (e,itemId) => {    
    setCart(itemId);
    }

 

완성된 코드들을 늘어놓아서 그렇지... 맨 처음에는 없는 상품이 추가는 되는데 (1)장바구니가 빈 뒤에 다시 물품이 채워지지 않는 현상 (2) 여러번 담을 경우 계속해서 상품의 양이 1로 고정되어 있는 현상 이렇게 두 가지 엣지케이스가 있었는데...  구현하고자하는 방식에 따라서 (2)은 나름 의도한 것이었지만(수량 조절은 장바구니에서만 하게하고싶었다.) (1)과 같은 현상은 엣지케이스라기에는 치명적인 단점인데, 처음 가입한 회원들은 장바구니가 주어진 과제처럼 차있는 것이 아니라 비어있을 것이기 때문이다. 따라서 해당 문제를 해결하는데 오래걸리지는 않았으나 주의깊게 테스트를 하는 습관을 들이는 것이 중요하다는 것을 깨달았다. 최소한의 기능은 잘 작동이 되어야하니까.

 

#3. 장바구니에서 상품수량 조정

이 부분은 쉽지는 않았는데, 일단 cartItems와 setCartItems를 props로 가져와서 조정해주는 것은 크게 어렵지 않았다. 그런데 맨 처음에는 state인 cartItems를 직접 조작하고 setCartItems를 호출해서 [...cartItems] 이렇게 다시 담아주면서 랜더링하는 바람직하지 못한 행위를 했다.

 

state를 직접 조작하는 것을 최대한 지양하고 setstate를 조작해야하는데 이 부분은 블로깅하면서 발견해서 위에서 깔끔하게 코드를 정리한 것을 참고하여 이렇게 작성하였다.

const handleQuantityChange = (quantity, itemId) => {
    
    // cartItems.filter(el => el.itemId === itemId)[0].quantity = quantity; 
    // 내 이전 코드를 잔재로 남겨놨다..

    setCartItems(cartItems.map(el => {if(el.itemId === itemId){
      el.quantity = quantity;
      return el;   
    } else {
      return el;
    }
  }))
  }

 

#4. 장바구니에서 삭제

삭제 기능은 이미 구현되어있는 체크를 제거하는 기능에 더하여 다음과 같이 작성했다. 동일한 내용들이 많으므로 생략!!

const handleDelete = (itemId) => {
    setCheckedItems(checkedItems.filter((el) => el !== itemId)) //체크해제
    setCartItems(cartItems.filter((el) => el.itemId !== itemId)) //해당항목제외하고 전부 state에 저장
  }

(음... 깔끔하게 작성했다..!! ㅎㅎ)

 

#5. map(그 외 고차함수 포함!!) 과 관련된 이슈 

프로그래머스를 풀 때도 자주 있었던 문제였으며, 이번에 페어이신 분도 이 문제를 확실하게 겪어서 그 문제를 해결하다가 이번에 정리가 되었다. map,filter 등 고차함수를 사용하면서 콜백함수에 화살표 함수를 자주 사용하다보니 생략하는 문법들과 혼동돼서 중괄호{}가 있는지 여부에 따라 return문이 꼭 들어가야하는지 아닌지 여러가지 상황이 있는데 그런 것들을 잘 모르고 하다보니 어려움이 자주 있었다.
여기에서 도움을 받았다.

 

여기에서 줄이고 Redux 공부를 하러 떠나보자...😌

 

'study > TIL' 카테고리의 다른 글

[TIL No.22] 웹 표준, Sementic HTML  (0) 2023.03.02
[TIL No.21] Git-commit-convention / Redux  (0) 2023.02.27
[TIL No.18]React_Custom_Components  (1) 2023.02.21
[TIL No.17] React_CDD, CSS_in_js  (0) 2023.02.20
[TIL No. 16] 피그마(Figma) 클론  (1) 2023.02.17