검색 필터 기능을 구현해보자!
만들 예제의 완성본
1. 가게 이름을 검색하면 해당 검색어와 일치하는 가게가 필터 돼서 뜬다.
2. 해당하는 가게가 없을 경우 "검색 결과가 없습니다."가 뜬다.
구현 코드
List.jsx (리스트 페이지)
import React, {useState} from "react";
import styles from "./List.module.css";
import ListSearch from "../../components/ListSearch/ListSearch";
import {data} from "../../const/data";
import {ListBox} from "../../components/ListBox/ListBox";
const List = () => {
const [searchTerm, setSearchTerm] = useState(""); // 검색창 상태 관리
// 타이틀 포함한것만 필터
const filteredData = data.filter((item) => item.title.toLowerCase().includes(searchTerm.toLowerCase()));
// filter메서드는 제공된 함수에 의해 구현된 테스트를 통과한 모든 요소가 포함된 새 배열을 만든다.
// 필터 함수의 조건이 (title에 있는 글자를 포함하는 것이) true인 경우 해당 요소가 배열에 들어간다.
// state를 업데이트 해주는 함수
const onSearch = (term) =>{
setSearchTerm(term)
}
return (
<>
<div className={styles["list-component-container"]}>
<ListSearch searchTerm={searchTerm} onSearch={onSearch} />
</div>
<section className={styles["list-list-container"]}>
{filteredData && filteredData.length > 0 ? (
<div className={styles["list-list-box-container"]}>
{filteredData.map((el) => {
// title에 해당하는 배열을 map 돌림
return <ListBox key={el.id} {...el} />;
})}
</div>
) : (
<span className={styles["list-no-search-result"]}>검색 결과가 없습니다.</span>
)}
</section>
</>
);
};
export default List;
ListSearch.jsx (검색창 컴포넌트)
import styles from "./ListSearch.module.css";
import Magnifier from "../../assets/magnifier.png";
const ListSearch = ({onSearch, searchTerm}) => {
const handleInputChange = (event) => {
const term = event.target.value; // term은 입력하는 글자
onSearch(term); // 검색하는 글자(term)로 실시간으로 상태를 업데이트
};
return (
<div className={styles["list-search-container"]}>
<div className={styles["list-search-img-container"]}>
<a href="#">
<img src={Magnifier} alt="돋보기" />
</a>
</div>
<input className={styles["list-search-input-container"]} placeholder="검색어를 입력해 주세요." maxLength={20} value={searchTerm} onChange={handleInputChange} />
</div>
);
};
export default ListSearch;
코드 설명
1. List.jsx (리스트페이지)에서 useState를 써서 검색창의 상태를 관리한다.
const [searchTerm, setSearchTerm] = useState("");
2. List.jsx (리스트페이지)에서 seachTerm의 상태를 업데이트 해주는 onSearch 함수를 만든다.
const onSearch = (term) =>{
setSearchTerm(term)
}
3. ListSearch.jsx (검색창 컴포넌트)에 상태와 함수를 props로 전달한다.
<ListSearch searchTerm={searchTerm} setSearchTerm={setSearchTerm} onSearch={onSearch} />
4. ListSearch.jsx (검색창 컴포넌트)에서 props를 전달 받는다.
const ListSearch = ({onSearch, searchTerm}) => {
···
5. ListSearch.jsx (검색창 컴포넌트)에서 검색창에서의 사용자의 입력값을 받아서 상태를 실시간으로 업데이트하는 handleInputChange 함수를 만든다.
const handleInputChange = (event) => {
const term = event.target.value; // term은 입력하는 글자
onSearch(term); // 검색하는 글자(term)로 실시간으로 상태를 업데이트
};
6. ListSearch.jsx (검색창 컴포넌트)에서
<input>의 value 값으로 searchTerm (state)를 달고,
<input>의 onChange이벤트로 handleInputChange 함수를 단다.
<input className={styles["list-search-input-container"]} placeholder="검색어를 입력해 주세요." maxLength={20} value={searchTerm} onChange={handleInputChange} />
7. List.jsx(페이지) 에서 title을 포함하는 단어만 필터해주는 filteredData 변수를 만든다.
*참고) 여기서 data는 음식점 정보를 담은 배열 (더미데이터)이며, title은 음식점 이름이다.
const filteredData = data.filter((item) => item.title.toLowerCase().includes(searchTerm.toLowerCase()));
// filter메서드는 제공된 함수에 의해 구현된 테스트를 통과한 모든 요소가 포함된 새 배열을 만든다.
// 필터 함수의 조건이 (title에 있는 글자를 포함하는 것이) true인 경우 해당 요소가 배열에 들어간다.
8. List.jsx(페이지)에서 filteredData(필터된 배열)을 <ListBox /> 컴포넌트에다가 map을 돌린다.
이렇게 하면 필터된 배열만 리스트에 뜨게 된다.
<div className={styles["list-list-box-container"]}>
{filteredData.map((el) => {
return <ListBox key={el.id} {...el} />;
})}
</div>
*참고) ListBox.jsx 컴포넌트 코드
import styles from "./ListBox.module.css";
import Like from "../../assets/detail/purple-thumb.png";
import Jjim from "../../assets/detail/red-heart.png";
import {useNavigate} from "react-router-dom";
export const ListBox = (props) => {
const navigate = useNavigate();
return (
<>
<button
onClick={() => {
navigate(`/DetailMenu/${props.id}`);
}}
className={styles["list-box-container"]}
>
<div className={styles["list-box-inner-container"]}>
<span className={styles["list-box-title"]}>{props.title}</span>
<div className={styles["list-box-like-jjim-container"]}>
<div className={styles["list-box-jjim"]}>
<img src={Jjim} alt="찜 아이콘" style={{position: "absolute", top: "0px", width: "23px", height: "23px"}} /> <span className={styles["list-box-jjim-number"]}> {props.jjim}</span>
</div>
<div className={styles["list-box-like"]}>
<img src={Like} alt="좋아요 아이콘" style={{position: "absolute", top: "-1px", width: "24px", height: "24px"}} />
<span className={styles["list-box-like-number"]}> {props.like}</span>
</div>
</div>
<span className={`${styles["list-box-runtime"]} ${props.runTime === "영업 준비 중" ? styles["ready"] : ""} `}> {props.runTime}</span>
<span className={styles["list-box-intro"]}>{props.intro}</span>
<span className={styles["list-box-address-brief"]}>{props.addressBrief}</span>
<img className={styles["list-box-img1"]} src={props.src1} />
<img className={styles["list-box-img2"]} src={props.src2} />
<img className={styles["list-box-img3"]} src={props.src3} />
</div>
</button>
</>
);
};
9. "검색 결과가 없습니다"를 뜨게 하기 위해서 삼항연산자를 이용한다.
filteredData가 1개 이상이면, 리스트가 뜨게하고,
그게 아니면 "검색 결과가 없습니다."가 뜨게 한다.
{filteredData && filteredData.length > 0 ? (
<div className={styles["list-list-box-container"]}>
{filteredData.map((el) => {
return <ListBox key={el.id} {...el} />;
})}
</div>
) : (
<span className={styles["list-no-search-result"]}>검색 결과가 없습니다.</span>
)}
10. 완성본
서버와 통신하면서 검색어 필터링을 하는 방법이 궁금하시다면 아래의 게시글을 참고해주세요!
https://dev-ini.tistory.com/270
[Next.js] 서버와 통신을 통해 검색창, 검색어, 검색 필터 기능 구현하기 (검색창 만들기) React, TypeSc
Next.js, React, TypeScript를 사용하여 서버와 통신하여 검색창 필터 기능을 구현하는 방법을 알아보자! 만들 예제의 완성본 검색창에 키워드를 검색하면, 해당 검색 결과와 일치하는 데이터를
dev-ini.tistory.com
최신순, 오래된순 등등 필터링에 대해 궁금하시다면 아래의 게시글을 참고해주세요!
https://dev-ini.tistory.com/103
[React] 리액트에서 필터(filter)기능 구현, 최신순/오래된순 등등 필터링
리액트에서 필터 기능을 구현해보자! 만들 예제의 완성본 1. 최신순/오래된순 필터 만들기 1. 컴포넌트를 만든다. DiaryList.js import { useState } from "react"; const ControlMenu = ({value, onChange, optionList}) => { //
dev-ini.tistory.com
'Libraries > React' 카테고리의 다른 글
[React] Routing (5) 데이터에서 route 설정하기 (0) | 2024.01.03 |
---|---|
[React] Filter (3) 리스트 카테고리 필터링 (0) | 2023.12.31 |
[React] props 완전 정복기 (props 개념 쉽게 이해하기) (0) | 2023.12.24 |
[React] map과 find를 사용해서 데이터 리스트 렌더링 하기 (0) | 2023.12.22 |
[React] 데이터 값에 따라 CSS 스타일 다르게 지정하기 (3) | 2023.12.21 |