이번에는 검색해서 특정 단어를 입력할때 검색한 단어에 맞춰 필터링 되는 검색바를 구현하려고 합니다. SearchBar
라는 이름의 컴포넌트를 생성해줬습니다.
앗...아아
저번에 작성했던 코드에서 약간 수정해주고 추가해줬습니다. 아래 코드는 추가되거나 수정된 부분만 보여드립니다
검색 필터링을 위해 상대변수를 더 추가해줬습니다.
export default function Display() {
const [activeCat, setActiveCat] = useState("All");
const [data, setData] = useState([]); //수정된 부분
const [search, setSearch] = useState("");
const [filterVga, setFilterVga] = useState([]);
useEffect(() => {
activeCat === "All"
? setData(items)
: setData(items.filter((vga) => vga.company === activeCat));
}, [activeCat]);
기존 코드에서는 data
라는 상태변수에 더미데이터를 담아줬었지만 이번에는 빈 배열로 수정했습니다..
왜냐하면 아래의 useEffect에서 카테고리 버튼 필터링을 위해 setData로 items를 담아줬기 때문에 굳이 넣어줄 필요가 없기때문입니다.
...
useEffect(() => {
setFilterVga(
data.filter((gpu) =>
gpu.model.toLowerCase().includes(search.toLowerCase())
)
);
}, [search, data]);
const renderList = filterVga.map((g, i) => {
return (
<div className="card_container">
<Card card={g} key={i} />
</div>
);
});
console.log(data);
검색 필터링 기능을 위한 useEffect
를 하나 더 추가해줍니다. 두 번째 인자로 search와 data를 담아줬습니다.
제공된 더미데이터에서 model의 값을 찾아 소문자로 바꿔주고, search에서 입력된 값과 일치하는지 찾아내줍니다. toLowerCase()를 사용해줬기 때문에 대문자를 입력해도 소문자로 들어갑니다. 어쨌든 입력할 경우 일치하는 데이터만을 렌더링 해줍니다.
return (
<main>
...
<SearchBar onChange={(e) => setSearch(e.target.value)} />
<article className="card_list">
{renderList.length > 0 ? (
renderList
) : (
<p>제품이 존재하지 않습니다.</p>
)}
</article>
...
</main>
);
SearchBar
컴포넌트에 onChange에 작성된 함수를 props로 전달해주었습니다.(이게 맞는소린지 헷갈리네요)
e.target.value
로 입력된 값을 Search로 전달해줍니다.
export default function SearchBar({ onChange }) {
return (
<form className="search">
<input
type="text"
placeholder="제품을 검색해보세요. ex)RTX..., RX.."
className="search_bar"
name="searchText"
onChange={onChange}
/>
</form>
);
}
.search {
margin: 2%;
display: flex;
position: relative;
border-radius: 20px;
border: 5px solid rgba(11, 195, 11, 0.74);
background: white;
width: 60%;
}
.search_bar {
width: 100%;
height: 50px;
border: none;
border-radius: 20px;
outline: none;
font-size: 1.1rem;
padding: 5px;
}
.search:hover {
box-shadow: 0 0 7px rgba(11, 195, 11, 0.74);
}