728x90
리액트에서 카테고리 필터링 하는 방법을 알아보자!
만들 예제의 완성본
파일 구성
App.js : 메인페이지
List.jsx (컴포넌트) : 리스트아이템이 합쳐진 리스트들
ListItem.jsx (컴포넌트) : 리스트 개별 아이템
Filter.jsx (컴포넌트) : 필터
data.js : 더미데이터
파일 구조
- App.js에서 List.jsx(리스트들)와 Filter.jsx(필터)를 import한다.
- List.jsx(리스트들)에서는 ListItem.jsx(리스트아이템)를 import한다.
- App.js에서는 data.js(더미데이터)를 import한다. 그리고 이 데이터를 필터해서 List.jsx(리스트들)에게 전달해줄 것이다.
1. 기본 마크업을 한다.
App.js
import { Filter } from "./Filter";
import { List } from "./List";
import "./styles.css";
import { data } from "./data.js";
export default function App() {
return (
<div className="App">
<header>
<h1>머신사</h1>
</header>
<Filter />
<List data={data} /> // 데이터 전달
</div>
);
}
List.jsx
import "./List.css";
import { ListItem } from "./ListItem";
export const List = ({ data }) => {
return (
<div className="list-container">
{data.map((it) => {
return <ListItem key={it.id} {...it} />;
})}
</div>
);
};
ListItem.jsx
import "./ListItem.css";
export const ListItem = (props) => {
return (
<div>
<div className="list-item-container">{props.title}</div>
</div>
);
};
Filter.jsx
export const Filter = () => {
return (
<div>
<div className="filter-container">
<button type="button" className="all"> 전체 </button>
<p className="filter-bar"> | </p>
<button type="button" className="top"> 상의 </button>
<p className="filter-bar"> | </p>
<button type="button" className="bottom"> 하의 </button>
<p className="filter-bar"> | </p>
<button type="button" className="outer"> 아우터 </button>
</div>
</div>
);
};
data.js
export const data = [
{
id: 1,
category: "top",
title: "상의1",
},
{
id: 2,
category: "top",
title: "상의2",
},
{
id: 3,
category: "top",
title: "상의3",
},
{
id: 4,
category: "bottom",
title: "하의1",
},
{
id: 5,
category: "bottom",
title: "하의2",
},
{
id: 6,
category: "bottom",
title: "하의3",
},
{
id: 7,
category: "outer",
title: "아우터1",
},
{
id: 8,
category: "outer",
title: "아우터2",
},
{
id: 9,
category: "outer",
title: "아우터3",
},
];
기본적 마크업을 끝내면, 아래와 같이 화면에 뜬다.
2. App.js에서 선택된 카테고리 필터의 state를 설정하고, state를 props로 Filter 컴포넌트에 전달해준다.
App.js
import { Filter } from "./Filter";
import { List } from "./List";
import "./styles.css";
import { data } from "./data.js";
import { useState } from "react";
export default function App() {
const [selectedCategory, setSelectedCategory] = useState("all"); // state의 기본값은 전체보기(all)
return (
<div className="App">
<header>
<h1>머신사</h1>
</header>
<Filter
setSelectedCategory={setSelectedCategory} // setState 전달
selectedCategory={selectedCategory} // state 전달
/>
<List data={data} />
</div>
);
}
3. Filter.jsx에서 props로 state를 전달 받고, onClick 이벤트에 setState를 달아서, 특정 카테고리를 클릭하면 해당 카테고리로 상태를 바뀌게끔 설정해준다.
Filter.jsx
import "./Filter.css";
export const Filter = ({setSelectedCategory, selectedCategory}) => {
return (
<div>
<div className="filter-container">
<button
type="button"
className="all"
onClick={() => setSelectedCategory("all")}
>
전체
</button>
<p className="filter-bar"> | </p>
<button
type="button"
className="top"
onClick={() => setSelectedCategory("top")}
>
상의
</button>
<p className="filter-bar"> | </p>
<button
type="button"
className="bottom"
onClick={() => setSelectedCategory("bottom")}
>
하의
</button>
<p className="filter-bar"> | </p>
<button
type="button"
className="outer"
onClick={() => setSelectedCategory("outer")}
>
아우터
</button>
</div>
</div>
);
};
4. App.js에서 데이터의 카테고리가 (선택된 카테고리인) state인 것들(=selectedCategory)로 필터하고,
List.jsx 컴포넌트에 filter한 데이터(filteredList)를 props로 넘겨준다.
App.js
import { Filter } from "./Filter";
import { List } from "./List";
import "./styles.css";
import { data } from "./data.js";
import { useState } from "react";
export default function App() {
const [selectedCategory, setSelectedCategory] = useState("all");
// state가 "all"이면 data 전체를 넘겨주고, 그게 아니면 선택된 category에 해당하는 데이터만 filter해서 넘겨준다.
const filteredList =
selectedCategory === "all"
? data
: data.filter((item) => item.category === selectedCategory);
return (
<div className="App">
<header>
<h1>머신사</h1>
</header>
<Filter
setSelectedCategory={setSelectedCategory}
selectedCategory={selectedCategory}
/>
<List filteredList={filteredList} /> // filteredList를 props로 넘겨줌
</div>
);
}
5. List.jsx에서 필터한 데이터 (filteredList)를 props로 받고 map을 돌린다.
List.jsx
import "./List.css";
import { ListItem } from "./ListItem";
export const List = ({ filteredList }) => {
return (
<div className="list-container">
{filteredList.map((it) => {
return <ListItem key={it.id} {...it} />;
})}
</div>
);
};
필터 기능이 완성 되었다.
6. 해당 필터를 선택했을때 "글자파란색+밑줄" CSS가 유지되게하기
삼항연산자를 사용하여 state에 따라 className이 바뀌게 한다.
Filter.jsx
import "./Filter.css";
export const Filter = ({ selectedCategory, setSelectedCategory }) => {
return (
<div>
<div className="filter-container">
<button
type="button"
onClick={() => setSelectedCategory("all")}
className={`${"all"} ${
selectedCategory === "all" ? "filter-active" : ""
}`}
>
전체
</button>
<p className="filter-bar"> | </p>
<button
type="button"
onClick={() => setSelectedCategory("top")}
className={`${"top"} ${
selectedCategory === "top" ? "filter-active" : ""
}`}
>
상의
</button>
<p className="filter-bar"> | </p>
<button
type="button"
onClick={() => setSelectedCategory("bottom")}
className={`${"bottom"} ${
selectedCategory === "bottom" ? "filter-active" : ""
}`}
>
하의
</button>
<p className="filter-bar"> | </p>
<button
type="button"
className="outer"
onClick={() => setSelectedCategory("outer")}
className={`${"outer"} ${
selectedCategory === "outer" ? "filter-active" : ""
}`}
>
아우터
</button>
</div>
</div>
);
};
Filter.css
.filter-container {
background: white;
color: black;
display: flex;
gap: 10px;
width: 240px;
height: 45px;
margin-top: 20px;
text-align: center;
justify-content: center;
}
.filter-container button:hover {
color: blue;
text-decoration: underline;
cursor: pointer;
font-weight: 600;
}
.all,
.top,
.bottom,
.outer {
all: unset;
}
.filter-bar {
margin-top: 10px;
}
.filter-active {
all: unset;
font-weight: 600;
color: blue;
text-decoration: underline;
}
전체를 클릭했을 때 className이 바뀐다.
완성본
728x90
'Libraries > React' 카테고리의 다른 글
[React] 중복된 useState 상태 및 함수 코드 정리하기, 컴포넌트 분리하기 (0) | 2024.01.04 |
---|---|
[React] Routing (5) 데이터에서 route 설정하기 (0) | 2024.01.03 |
[React] Filter (2) 검색창, 검색어, 검색 필터 기능 구현 (검색창 만들기) (2) | 2023.12.28 |
[React] props 완전 정복기 (props 개념 쉽게 이해하기) (0) | 2023.12.24 |
[React] map과 find를 사용해서 데이터 리스트 렌더링 하기 (0) | 2023.12.22 |