체크박스를 이용한 카테고리 검색 만들기

적자생존·2022년 7월 9일
1

teamprojectReview

목록 보기
17/18

1. 구현하고자 하는 기능

체크박스를 이용한 카테고리 검색 기능은 팀 프로젝트의 핵심 기능이였다.

가. 각각의 카테고리를 클릭하면 각 카테고리를 태그로 입력한 글들을 보여주는 기능

나. 다른 카테고리를 클릭하면 기존의 선택된 카테고리가 사라지는 기능

다. 다른 카테고리를 클릭하면 추가로 카테고리가 선택되는 기능

2. 체크박스를 이용해서 카테고리 검색 구현하기

가. 메뉴 카테고리에서 카테고리를 클릭하면 해당하는 카테고리의 글을 보여주고 다른 카테고리를 클릭하면 기존의 카테고리 선택이 사라짐

1) 메뉴 필터 페이지에 카테고리 데이터를 만들어준다.

const menuData = [
    { key: "0", value: "비건", checked: false, index: 0 },
    { key: "1", value: "아시안푸드", checked: false, index: 1 },
    { key: "2", value: "양식", checked: false, index: 2 },
    { key: "3", value: "일식", checked: false, index: 3 },
    { key: "4", value: "중식", checked: false, index: 4 },
    { key: "5", value: "한식", checked: false, index: 5 },
    { key: "6", value: "할랄", checked: false, index: 6 },
  ];

가) menuData라는 변수에 카테고리의 데이터를 만들어서 할당을 해준다.

나) key의 경우 mapkey값을 위해 사용

다) value는 각각의 카테고리 값

라) checked는 CSS와 카테고리가 check 된 상태인지 확인하기 위해서 사용

마) index는 의미가 없었네,,,

2) 체크를 하는 함수를 생성

const onChangeMenu = (checked: any, item: any) => {
    if (checked) {
      props.setMenuTagCheckList([item]);
      props.setMenuHashTag([item]);
    } else if (!checked) {
      props.setMenuHashTag(props.menuHashTag.filter((el) => el !== item));
      props.setMenuTagCheckList(
        props.menuTagCheckList.filter((el) => el !== item)
      );
    }
  };

가) onChangeMenu라는 함수를 생성하고 인자로 checkeditem을 받아준다.
checkedmenuDatachecked 값이고 itemmenuDatavalue값이다.

나) menuHashTag, setMenuHashTag, menuTagCheckList, setMenuTagCheckList는 상위 컴포넌트에서 받아온 state이다

menuHashTag, setMenuHashTag는 선택한 태그를 관리하는 state이다
menuTagCheckList, setMenuTagCheckList는 선택한 태그가 체크 되었는지 관리하는 state인데 지금보니 필요가 없다.

다) onChangeMenu함수의 인자값인 itemchecked 상태(선택)가 true가 되고 item의 상태가 true가 되면 menuHashTag 배열에 추가 된다.

라) 만약 다시 클릭을 하면 checked의 상태가 false가 되고 menuHashTag에서 빠진다.

props.setMenuHashTag(props.menuHashTag.filter((el) => el !== item));

menuHashTag의 배열에서 filter함수를 이용해서 기존에 들어있는 item과 같지 않은 것들만 menuHashTag에 남게 된다.

즉 똑같은 item을 클릭하면 기존의 item은 제외가 되는 것이다.

3) presenter부분

{menuData.map((el) => (
        <label className="checkbox" key={el.key}>
          <input
            type="checkbox"
            value={el.value}
            onChange={(e) => {
              onChangeMenu(e.target.checked, e.target.value);
            }}
            checked={props.menuTagCheckList.includes(el.value)}
          />
          <span className="checkbox_text">{el.value}</span>
        </label>
      ))}

가) menuDatamap 함수를 이용해서 만들어 카테고리를 생성한다.

나) inputcheckbox로 만들어 주고 value 값은 menuDatavalue값으로 설정해둔다.

다) onChange함수에 event(e)를 주고 위에서 만든 onChangeMenu를 바인딩 해주고 event의 target에 있는 checkedvalue값을 인자로 넘겨준다.

라) checked 상태를 menuTagCheckList를 줬는데 menuHashTag로 줘도 상관이 없다. menuHashTag에 있는 값(item)이 includes를 이용해 menuData의 값과 일치하는 지 확인한다. 즉 일치하면 checked상태가 true가 되는 것이다.

마) 체크박스의 값을 menuDatavalue값으로 설정한다.

4) CSS부분

export const OpenTag = styled.div`
  display: flex;
  flex-wrap: wrap;
  font-weight: 700;
  font-size: 16px;
  .checkbox input {
    display: none;
  }

  .checkbox {
    display: flex;
    margin: 0px 30px 10px 0px;
    @media ${breakPoints.mobile} {
    margin: 0 6px 8px 0;
  }
  }

  .checkbox_text {
    display: flex;
    background-color: #d2d2d2;
    margin-left: 10px;
    font-size: 16px;
    color: #ffffff;
    padding: 7px 20px;
    border-radius: 50px;
    cursor: pointer;
    &:hover {
      background-color: #ff9a31;
      color: #ffffff;
    }
  }

  .checkbox input:checked + .checkbox_text {
    color: #ffffff;
    background-color: #ffa230;
  }
`;

미디어 부분은 제외했다.

가) 기존의 CSS를 제외하고 선택된 상태에서 CSS만 보면

.checkbox input:checked + .checkbox_text {
    color: #ffffff;
    background-color: #ffa230;
  }

inputchecked가 되고 checkbox_text이라는 className을 가진 태그를 colorbackground-color를 변경해준다.

나. 분위기 카테고리에서 카테고리를 클릭하면 해당하는 카테고리의 글을 보여주고 다른 카테고리를 클릭하면 기존의 카테고리에 선택한 카테고리가 추가됨

1) 와 동일하나 함수부분이 상이함

const onChangeMood = (checked, item) => {
    if (checked) {
      props.setMoodHashTag([...props.moodHashTag, item]);
    } else if (!checked) {
      props.setMoodHashTag(props.moodHashTag.filter((el) => el !== item));
    }
  };

가) setMoodHashTag에서 에서는 기존의 item 하나만 들어갔으나 스프레드 연산자를 이용해서 기존의 아이템에 새로 선택된 아이템을 추가해준다.
...props.moodHashTag

나) 역시 filter를 이용해서 같은 것이 선택되면 배열에서 제외되도록 해준다.

다) CSS역시 동일하다

3. 전체코드

가. 기존의 선택된 카테고리 제거하기

export default function MenuFilterPage(props: any) {
  const menuData = [
    { key: "0", value: "비건", checked: false, index: 0 },
    { key: "1", value: "아시안푸드", checked: false, index: 1 },
    { key: "2", value: "양식", checked: false, index: 2 },
    { key: "3", value: "일식", checked: false, index: 3 },
    { key: "4", value: "중식", checked: false, index: 4 },
    { key: "5", value: "한식", checked: false, index: 5 },
    { key: "6", value: "할랄", checked: false, index: 6 },
  ];

  const onChangeMenu = (checked: any, item: any) => {
    if (checked) {
      props.setMenuTagCheckList([item]);
      props.setMenuHashTag([item]);
    } else if (!checked) {
      props.setMenuHashTag(props.menuHashTag.filter((el: any) => el !== item));
      props.setMenuTagCheckList(
        props.menuTagCheckList.filter((el: any) => el !== item)
      );
    }
  };
  return (
    <S.OpenTag>
      {menuData.map((el) => (
        <label className="checkbox" key={el.key}>
          <input
            type="checkbox"
            value={el.value}
            onChange={(e) => {
              onChangeMenu(e.target.checked, e.target.value);
            }}
            checked={props.menuTagCheckList.includes(el.value)}
          />
          <span className="checkbox_text">{el.value}</span>
        </label>
      ))}
    </S.OpenTag>
  );
}

나. 기존의 카테고리에 선택된 카테고리 추가하기

export default function MoodFilterPage(props: any) {
  const moodData = [
    { key: "0", value: "가족들과", checked: false, index: 0 },
    { key: "1", value: "동창회자리로좋은", checked: false, index: 0 },
    { key: "2", value: "부모님과함께", checked: false, index: 0 },
    { key: "3", value: "소개팅", checked: false, index: 0 },
    { key: "4", value: "술자리로좋은", checked: false, index: 0 },
    { key: "5", value: "썸타는사람과", checked: false, index: 0 },
    { key: "6", value: "애인과함께", checked: false, index: 0 },
    { key: "7", value: "친구와함께", checked: false, index: 0 },
    { key: "8", value: "혼밥하기좋은", checked: false, index: 0 },
    { key: "9", value: "혼술하기좋은", checked: false, index: 0 },
    { key: "10", value: "회식자리로좋은", checked: false, index: 0 },
  ];

  const onChangeMood = (checked: any, item: any) => {
    if (checked) {
      props.setMoodHashTag([...props.moodHashTag, item]);
    } else if (!checked) {
      props.setMoodHashTag(props.moodHashTag.filter((el: any) => el !== item));
    }
  };

  return (
    <S.OpenTag>
      {moodData.map((el) => (
        <label className="checkbox" key={el.key}>
          <input
            type="checkbox"
            value={el.value}
            onChange={(e) => {
              onChangeMood(e.target.checked, e.target.value);
            }}
            checked={props.moodHashTag.includes(el.value)}
          />
          <span className="checkbox_text">
            <img className="check_icon" src="/images/check.png" />
            {el.value}
          </span>
        </label>
      ))}
    </S.OpenTag>
  );
}
  1. 체크가 되었는지 확인하기

체크를 구현하였기 때문에 체크가 진짜 잘 되었는지 확인할 필요가 있다.

가. 고차함수 이용하기

const onChangeCheckMenu = (el: any) => (event: any) => {
    const select = menuTagData.map((el, idx) => {
      return { ...el, checked: idx === Number(event.target.id) };
    });
    setMenuTagData(select);

    setBoardTagMenu(el.value);
  };

container부분

{props.menuTagData.map((el: any, idx: any) => (
                  <label className="checkbox" key={el.key}>
                    <input
                      type="checkbox"
                      id={String(idx)}
                      onChange={props.onChangeCheckMenu(el)}
                      checked={Boolean(el.checked)}
                    />
                    <span className="checkbox_text">{el.value}</span>
                  </label>
                ))}

presenter 부분

presenter부분에서 map을 돌린 이후 데이터들을 onChangeCheckMenu의 인자로 넣어준다.

이후에

onChangeCheckMenu는 el을 인자값으로 받아오는 HOF으로 만들어 준다.

이때 두번째 인자값으로는 event를 넣어준다.

select라는 변수를 만들어 주고 여기에 메뉴태그데이터를 map함수를 이용해서 클릭해서 해당 menuData의 checked값을 true 변경하도록 하는데 이때 다시 클릭이 되었을 경우에 id값을 확인하여 다를 경우 두번째 선택된 데이터의 checked를 true로 같을 경우는 기존의 것을 true로 하라고 만들어 준다.

이후 select를 setMenuTagData에 넣어주면 ...el로 인해 변경된 값만 true로 변경된다.

setBoardTagMenu에는 el.value가 들어가게 된다.

presenter부분에서 input의 checked에는 el.checked가 들어가 있기 때문에 태그 데이터에서 checked된 것만 배열로 들어갈 수 있다.

profile
적는 자만이 생존한다.

0개의 댓글