[React] 리액트 수량 더하기, 빼기 버튼 구현하기

이은진·2021년 1월 3일
3

React Study

목록 보기
3/10
post-thumbnail
post-custom-banner

리액트로 프로젝트를 진행하던 중, 필터 팝업에서 plus, minus 버튼을 구현하게 되었다. 처음에는 대체 어떻게 접근할지 감이 안 왔는데, 차근차근 접근하다 보니 구현할 만 했다. 다른 기능들이 워낙 헬이었어서...

내 경우, 백엔드에서 필터링 항목에 대한 데이터를 모두 한 번에 보내줄 것을 가정하고 로직을 짜다 보니 생각보다 복잡해졌다. '침실과 침대' 항목과 '편의시설', '시설', 그리고 그 아래의 건물 유형, 지역 필터까지 여러 가지가 있었는데, '침실과 침대' 항목만 갯수 더하기, 빼기 형태를 하고 있었고, 나머지 항목들은 체크를 하는 방식이었다. 그래서 필터 항목 리스트 중, 첫 번째 항목인 침실과 침대를 따로 빼고, 나머지는 map 메서드로 돌려서 컴포넌트화해서 구현했다.

1. 부모 컴포넌트에서 수량 변경하는 함수 만들기

  // [필터 추가하기] -> [침실과 침대] 항목 수량 변경 기능
  const handleModifyBtn = (id, type) => {
    let modifiedListTemp = [];
    let modifiedStatus = filters[0].filterChecked;
    type === "plus" ? modifiedStatus[id]++ : modifiedStatus[id]--;
    filters[0].filterItem.forEach((item, index) => {
      modifiedListTemp.push({
        name: item,
        amount: modifiedStatus[index],
      });
    });
    const filteredItemTemp = {
      filterType: filters[0].filterType,
      filteredItem: modifiedListTemp,
    };
    setBedFilter(filteredItemTemp);
  };

위는 수량 변경 버튼을 클릭하는 함수다. 인자로 어떤 필터인지를 알 수 있는 id값과, 그것이 minus 타입인지, plus 타입인지를 알려주는 type을 갖는 함수다. 여기서 특이점은 modifiedListTemp 라는 배열을 따로 선언하고, filteredItemTemp라는 객체를 만들었다는 점이다. 이렇게 코드를 짠 이유는 백엔드에서 첫번째 필터 타입인 '침실과 침대'와 그 외의 필터 타입들을 일괄적으로 한번에 보내줄 것이라고 가정하고 목데이터를 만들었기 때문이다. 그 로직 때문에 조금 복잡해 보이는데, 결국 중간에 있는 이 코드가 핵심이다.

    type === "plus" ? modifiedStatus[id]++ : modifiedStatus[id]--;

인자로 넘겨 준 'type'이 'plus'이면 값을 추가하고, 'minus'이면, 즉 'plus' 가 아니면 값을 하나씩 빼는 코드다. 그리고 그렇게 바뀐 값을 변경된 값을 담는 리스트인 modifiedListTemp에 setState로 넣어주면 된다. 그럼 이 함수를 어떻게 필터 팝업 컴포넌트에서 불러왔는지 볼 차례다.

2. 필터 컴포넌트에서 함수 적용하기

    <Modifier className="modifier">
      {filteredCounts[id] < 1 ? (
        <MinusNoClick />
      ) : (
        <Minus onClick={() => handleModifyBtn(id, "minus")} />
      )}
        <div>{filteredCounts[id]}</div>
      <Plus onClick={() => handleModifyBtn(id, "plus")} />
    </Modifier>

필터 팝업 컴포넌트의 자식의 자식 컴포넌트인 BedFilterItem 컴포넌트에서 해당 함수를 불러왔다. 이렇게 너무 아래 자손까지 함수를 끌어다가 쓰는 것이 옳은 방식인지는 모르겠으나, 당장 기능을 구현해 놓고 나중에 시간을 갖고 리팩토링하자는 생각으로 일단 코드를 짰다.

앞서 수량조절 버튼에 적용할 함수가 handleModifyBtn이며, 두 개의 인자를 갖는다고 언급한 바 있다. minus 버튼에 해당하는 div 태그는 인자에 "minus"를, plus 버튼에 해당하는 div태그에는 인자에 "plus"를 주어서, 아까 부모의 부모의 부모 컴포넌트에서 함수 안에 삼항연산자에 따라 실행될 수 있도록 했다. 원래 같았으면 함수 작성에 익숙하지 않은 나는 plus 함수와 minus 함수를 따로 만들었을텐데, 역시나 이번에도 따로 만들었다가 코드리뷰를 받고 합치게 되었다.

추가로 조건부 렌더링과 스타일 언급하고 넘어가야겠다는 생각이 든다. 버튼의 가운데 위치한 수량이 1보다 작을 경우, 이라는 스타일 컴포넌트를 렌더하여, 비활성화된 버튼임을 확실히 알 수 있는 스타일로 속성값을 적용했다. 또한 아예 onClick 이벤트를 삭제함으로써 0보다 작은 수로는 내려가지 않도록 만들었다.

const Minus = styled.div`
  display: inline-block;
  width: 32px;
  height: 32px;
  background: linear-gradient(#000, #000), linear-gradient(#000, #000);
  background-position: center;
  background-size: 40% 2px;
  background-repeat: no-repeat;
  border: 1px solid rgba(0, 0, 0, 0.3);
  border-radius: 50%;
  cursor: pointer;
`;

const MinusNoClick = styled(Minus)`
  opacity: 0.15;
  border: 1px solid rgba(0, 0, 0, 0.8);
  cursor: default;
`;

const Plus = styled(Minus)`
  background-size: 40% 2px, 2px 40%;
`;
profile
빵굽는 프론트엔드 개발자
post-custom-banner

0개의 댓글