React - 다중 필터

보윤이의 기술 블로그·2022년 4월 24일
1

React

목록 보기
12/18
post-thumbnail

1. 구현하고 싶었던 기능

  • 다중 필터
    : 상수데이터 FILTER_LIST 내 category, value 값을 정해두고 Query parameter 를 이용하여 해당 버튼을 눌렀을 때 url 뒤에 &amenity=1 이렇게 추가될 수 있도록 로직 구현

2. 구현한 코드

const LIMIT = 12; // 한 페이지에 12개씩 보여준다
const qsArr = []; // 빈 배열로 url 을 관리한다

const Staylist = () => {
  const location = useLocation();
  const [isClicked, setIsClicked] = useState(false);
  const [placeList, setPlaceList] = useState([]);
  const [clickedList, setClickedList] = useState([]);
  const [buttonNum, setButtonNum] = useState(1);
  const [offsetNumber, setOffsetNumber] = useState(0);
  const navigate = useNavigate();
  const buttonRef = useRef();

  useEffect(() => {
    fetch(
      `${API.stays}${
        location.search ? location.search + '&' : '?'
      }limit=${LIMIT}&offset=${offsetNumber}`
    )
      .then(res => res.json())
      .then(data => setPlaceList(data.stay_list));
  }, [location.search, offsetNumber]);

  const updateUrl = (category, value) => {
    const queryString = `${category}=${value}`;
    qsArr.push(queryString);
    const newQueryString = qsArr.join('&');
    navigate(
      `/staylist?${newQueryString}&limit=${LIMIT}&offset=${offsetNumber}`
    );
  };

  const filterUrl = (category, value) => {
    const deletedUrl = `${category}=${value}`;
    const index = qsArr.indexOf(deletedUrl);
    qsArr.splice(index, 1);
    const newQueryString = qsArr.join('&');
    navigate(`/staylist?${newQueryString}`);
  };

  const updateOffset = ({ buttonIndex, number }) => {
    setOffsetNumber(buttonIndex * 12);
    setButtonNum(number);
  };

  const openModal = () => {
    setIsClicked(!isClicked);
  };
  
  return (
    <StaylistContainer>
      <StaylistMenu>
        <StaylistFilter>
          <div>
            <TypeBtn>요금</TypeBtn>
            <TypeBtn ref={buttonRef} onClick={openModal}>
              숙소 유형
            </TypeBtn>
            {isClicked && (
              <StayModal
                isClicked={isClicked}
                setIsClicked={setIsClicked}
                buttonRef={buttonRef}
                staytype={STAY_TYPE}
                clickedList={clickedList}
                setClickedList={setClickedList}
                updateUrl={updateUrl}
                filterUrl={filterUrl}
              />
            )}
          </div>
          {FILTER_LIST.map(({ filterId, name, category, value }) => (
            <StaylistFilterTab
              key={filterId}
              name={name}
              category={category}
              value={value}
              clickedList={clickedList}
              setClickedList={setClickedList}
              changeUrl={() => {
                if (clickedList.includes(name)) {
                  filterUrl(category, value);
                } else {
                  updateUrl(category, value);
                }
              }}
            />
          ))}
        </StaylistFilter>
      </StaylistMenu>
	  <PageNation>
        <Buttons updateOffset={updateOffset} buttonNum={buttonNum} />
      </PageNation>
    </StaylistContainer>
  );
};

const FILTER_LIST = [
  {
    filterId: 1,
    name: '수영장',
    category: 'amenity',
    value: 1,
  },
  {
    filterId: 2,
    name: '자쿠지',
    category: 'amenity',
    value: 2,
  },
  {
    filterId: 3,
    name: '바베큐',
    category: 'amenity',
    value: 3,
  },
  {
    filterId: 4,
    name: '무선 인터넷',
    category: 'service',
    value: 1,
  },
  {
    filterId: 5,
    name: '주방',
    category: 'service',
    value: 2,
  },
  {
    filterId: 6,
    name: '주차장',
    category: 'service',
    value: 3,
  },
];
profile
어제보다 오늘 더 성장하는 프론트엔드 개발자

0개의 댓글