Filter 구현하기

mineii
8 min readNov 24, 2023

--

SpotlightSeoul은 서울 곳곳의 다양한 문화 행사 정보를 제공하는 플랫폼이다.

문화 행사는 공연, 축제, 전시회 등 다양한 카테고리가 존재하고, 사용자의 니즈에 맞는 행사를 찾게 도와주는 것이 이 플랫폼의 주 목적이기에 필터(Filter) 기능이 필요했다. 필터 기능을 추가함으로써 카테고리, 비용, 지역 등에 따른 필터링 된 행사를 보여줄 수 있게 했다.

Filter

파란색 박스 (필터)

지역, 비용, 분야, 공연 기간, 공연명 총 5가지로 필터를 제공했다. 공연 진행되는 지역은 구별로 분류하였고 비용은 유료/무료, 분야는 공연/전시/축제/교육 및 체험/기타로 분류하였다.

const Cost = [{ value: '비용' }, { value: '유료' }, { value: '무료' }];

const Field = [
{ value: '분야' },
{ value: '공연' },
{ value: '전시' },
{ value: '축제' },
{ value: '교육/체험' },
{ value: '기타' },
];

이렇게 드롭다운(drop-down) 목록을 입력해주었다.

function Filter({
setIsFree,
setField,
setSubField,
setStartDate,
setEndDate,
}: {
setIsFree: (cost: string) => void;
setField: (field: string) => void;
setSubField: (subField: string) => void;
setStartDate: (startDate: string) => void;
setEndDate: (endDate: string) => void;
}) {
const onChangeCost = (e: React.ChangeEvent<HTMLSelectElement>) => {
let { value } = e.currentTarget;
if (value === '비용') value = '';
setIsFree(value);
};

const onChangeField = (e: React.ChangeEvent<HTMLSelectElement>) => {
let { value } = e.currentTarget;
if (value === '분야') value = '';
setField(value);
};

‘Filter’는 setIsFree, setField, setSubField, setStartDate, setEndDate라는 다섯 가지 함수를 props로 받는다.

  • onChangeCost: 비용을 선택하는 드롭다운 값이 변경되면 실행되는 함수이다. 값이 바뀌면, 그 값을 가져와 setIsFree 함수를 통해 상태를 업데이트하며, 값이 '비용'이면 빈 문자열로 설정된다.
  • onChangeField: 분야를 선택하는 드롭다운 값이 변경되면 실행되는 함수이다. 값이 바뀌면, 그 값을 가져와 setField 함수를 통해 상태를 업데이트하며, 값이 '비용'이면 빈 문자열로 설정된다.

드롭다운 목록을 선택함으로써 생성되는 변경 사항을 처리하고, 제공된 setter 함수를 사용하여 상태를 업데이트한다. 다른 필터도 마찬가지로 이와 같이 작성한다.

        {/* 비용 */}
<select className="mx-2 my-3 h-8" id="비용" onChange={onChangeCost}>
{Cost.map((item) => (
<option key={item.value} value={item.value}>
{item.value}
</option>
))}
</select>

{/* 분야 */}
<select className="mx-1 my-3 h-8" id="분야" onChange={onChangeField}>
{Field.map((item) => (
<option key={item.value} value={item.value}>
{item.value}
</option>
))}
</select>

<select> 태그는 옵션 메뉴를 제공하는 드롭다운 리스트(drop-down list)를 정의할 때 사용한다. 위에 작성해둔 Cost 배열을 참조하여 각 항목을 <option>으로 매핑해서 드롭다운 안에 표시한다. 분야도 비용과 마찬가지로 똑같이 진행한다.

MainPage.tsx에 작성된 코드이다.

  // 페이징을 위한 state
const [page, setPage] = useState<number>(1);
// 드롭다운 필터링을 위한 state
const [isFree, setIsFree] = useState<string>('');
const [startDate, setStartDate] = useState<string>('');
const [endDate, setEndDate] = useState<string>('');
const [field, setField] = useState<string>('');
const [subField, setSubField] = useState<string>('');
const searchResults = useRecoilValue(searchResultsState);

MainPage.tsx에서 정의한 state를 Filter.tsx에 props로 넘겨준다

  // Filter.tsx에서 받아온 state를 이용하여 API 연결
const FilterInformation = async () => {
try {
const response = await axios
.get<{ total_page_num: number; post_responses: PostCardData[] }>(
`http://localhost:8080/api/v1/festivals/category?isFree=${isFree}&endDate=${endDate}&page=${page}&strtDate=${startDate}&majorCodeName=${field}`,
)
.then((res) => res.data.post_responses);
console.log('filter', response);
setTest(response);
} catch (error) {
console.log(error);
}
};

FilterInformation 은 비동기 함수이며, API에 필터 정보를 기반으로 요청을 보내고, 해당 요청에 대한 응답을 처리한다.

useEffect(() => {
if (searchResults.length > 0) {
setTest(searchResults);
} else if (
isFree === '' &&
startDate === '' &&
endDate === '' &&
field === '' &&
subField === ''
) {
if (inView) {
MainPostInformation();
}
} else if (
isFree !== '' ||
startDate !== '' ||
endDate !== '' ||
field !== '' ||
subField !== ''
) {
FilterInformation();
}
}, [inView, searchResults, isFree, startDate, endDate, field, subField]);

useEffect 는 특정 상태값들이 변경될 때마다 실행되는데, 이 코드에서는 inView, searchResults, isFree, startDate, endDate, field, subField 값들이 변화할 때마다 작동한다.

  1. searchResults가 있으면 그 값을 setTest를 통해 설정한다.
  2. 모든 필터 상태값들이 비어있고 (isFree, startDate, endDate, field, subField가 모두 빈 문자열일 때), inViewtrue일 때 MainPostInformation 함수를 실행한다. 필터가 적용되지 않았을 때 전체 데이터를 가져오는 것이다.
  3. 필터 상태값들 중 하나라도 비어있지 않을 때 FilterInformation 함수를 실행한다. 이 때는 필터가 적용된 데이터를 가져온다.

--

--