📌 들어가며
간단한 tab (탭) 입니다.
탭, checkbox(체크박스) 선택 시 해당 내용 노출 기능이 구현되어 있습니다.
구현하면서 알게된 것들을 정리했습니다.
📌 구조 작성해보기
1. 제공하려는 데이터 작성
2. 제공된 데이터 title, nickName, communityCategoryCd 값 가져오기
3. 2에서 가져온 값 화면에 뿌려주기
4. 각각의 tab 버튼 클릭 시, 해당 내용 보여주기 (이때, tab 버튼 이름과 communityCategoryCd 를 비교해서 같은 것만 보여주기)
4-1. 선택한 버튼의 현재 상태의 값을 useState 활용해서 저장
4-2. 현재 선택된 버튼과 communityCategoryCd 비교해서 tab 내용 뿌려주기
4-3. 버튼 클릭 시, 활성화되는 css 추가
5. 체크박스 (이번 달) 버튼 추가
5-1. 현재 시간과 regDttm 값의 년도, 달을 비교해서 해당 달에 등록된 데이터만 필터링
6. 검색 기능 추가 useState 사용
📌 데이터 작성
[constants.js]
export const ITEMS = [
{
"communityContentSeq": "2683",
"title": "홈플러스 이번주 전단행사! 5/23~29",
"content": "미국 프라임등급 척아이롤이랑, 보리먹인돼지 항정살 50프로 할인하네요!",
"communityCategoryCd": "01",
"viewCnt": 415,
"commentCnt": 2,
"regDttm": "20240526104604",
"nickName": "팁글모아태산"
},
{
"communityContentSeq": "2686",
"title": "토스체크 카드 만원 오백원 캐시백",
"content": "이거 생각보다 쏠쏠하네요\n\n잘 활용하면 좋은 거 같아요\n\n백원이상 백원 캐시백도 있습니다",
"communityCategoryCd": "02",
"viewCnt": 270,
"commentCnt": 0,
"regDttm": "20240526201131",
"nickName": "aa"
},
{
"communityContentSeq": "2688",
"title": "페이북",
"content": "페이북에서 마이테그하고 구매하심 5000원 할인 됩니다 필요하신 분들 어서 사용하세요~",
"communityCategoryCd": "03",
"viewCnt": 220,
"commentCnt": 0,
"regDttm": "20240526210425",
"nickName": "스테이지"
},
{
"communityContentSeq": "2689",
"title": "도미노피자 포장 50% 할인",
"content": "28일까지 행사합니다.",
"communityCategoryCd": "02",
"viewCnt": 193,
"commentCnt": 1,
"regDttm": "20240526220914",
"nickName": "푸바오"
},
{
"communityContentSeq": "2681",
"title": "오늘도 CU에서 얼음컵 타기",
"content": "오늘도 CU에서 얼음컵 타세요",
"communityCategoryCd": "01",
"viewCnt": 316,
"commentCnt": 0,
"regDttm": "20240526100148",
"nickName": "정리걸"
},
{
"communityContentSeq": "2677",
"title": "토스페이 gs샵 14% 할인",
"content": "토스페이 경유",
"communityCategoryCd": "01",
"viewCnt": 360,
"commentCnt": 0,
"regDttm": "20240526010328",
"nickName": "뺘뱌뀨"
},
{
"communityContentSeq": "2684",
"title": "여름용 주방용품 세일하네요❗️",
"content": "여름용 주방용품 할인하네요!\nhttps://link.coupang.com/a/bC4Teu",
"communityCategoryCd": "03",
"viewCnt": 263,
"commentCnt": 0,
"regDttm": "20240526152039",
"nickName": "특가정보원",
},
{
"communityContentSeq": "2687",
"title": "GS 샵 띠꿀모으기",
"content": "GS 샵 티꿀모아서\n적립금처럼 사용해요^^",
"communityCategoryCd": "02",
"viewCnt": 171,
"commentCnt": 0,
"regDttm": "20240526202009",
"nickName": "gs샵띠끌모으기"
},
{
"communityContentSeq": "2678",
"title": "SK하이닉스 수익률 2424% ㄷㄷ.....",
"content": "엔비디아 열풍에\nSK하이닉스 주가가 20만원대를 넘겼네요...\n\n\n20년도에 자신의 주식 보유 현황을 인증했던 자사 직원이 최근 블라인드에 계좌 보유 현황을 재인증했는데 대박이네요 😳\n\n당시 주 당 7,800원 5,700주였는데\n여전히 5,700주를 보유 중...\n\n와 수익률 2424%.....ㄷㄷ\n\n\n저는...14만원 직전에 털었는데...\n왜 이런 선택을 했을까.....🫠\n물론 매입가는 완전 다르지만 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ\n\n\n그 분의 블라인드 인증 글 캡쳐해서 올려보아요 \n정말 수익률 대박입니다 👍🏻👍🏻👍🏻\n\n\n\n\n",
"communityCategoryCd": "02",
"viewCnt": 391,
"commentCnt": 1,
"regDttm": "20240426011959",
"nickName": "부자될꼬동"
},
{
"communityContentSeq": "2682",
"title": "엔비디아 액면분할 이후",
"content": ".\n.\n.\n.\n.\n\n오른다 vs 내린다",
"communityCategoryCd": "03",
"viewCnt": 187,
"commentCnt": 6,
"regDttm": "20240526100341",
"nickName": "업비트최대주주워렌버핏"
}
]
📌 제공 데이터에서 title, nickName, communityCategoryCd 값 가져와서 화면에 뿌려주기
[App.js]
import { useEffect, useState } from 'react';
import {ITEMS} from './constants';
function App() {
const [tabValue, setTabValue] = useState('all');
const [list, setList] = useState(ITEMS);
const onClickTab = (selectedTab) => {
setTabValue(selectedTab);
}
return (
<>
<div>
<input id="month_chk" type="checkbox"/>
<label for="month_chk">이번 달</label>
</div>
<div>
<div className="tab-list">
<button type="button" onClick={()=>onClickTab('all')}>전체</button>
<button type="button" onClick={()=>onClickTab('01')}>01</button>
<button type="button" onClick={()=>onClickTab('02')}>02</button>
<button type="button" onClick={()=>onClickTab('03')}>03</button>
</div>
<div>
<ul>
{list.map((item) => (
<li key={item.communityContentSeq}>
<div>title: {item.title}</div>
<div>nickName: {item.nickName}</div>
<div>communityCategoryCd: {item.communityCategoryCd}</div>
</li>
))
}
</ul>
</div>
</div>
</>
);
}
export default App;
각각의 버튼에 onClick={()=>onClickTab('01')} 과 같이 넣어준다.
이렇게 넣어놓으면 모든 내용을 다 불러오게 된다.
📌 tab 버튼 클릭 시, 해당 내용 보여주기
- tab 버튼 이름(all, 01, 02, 03) 과 communityCategoryCd 를 비교
- 선택한 버튼의 현재 상태의 값을 useState 활용해서 저장
- 현재 선택된 버튼과 communityCategoryCd 비교해서 tab 내용 뿌려주기
- 버튼 클릭 시, 활성화되는 css 추가
[ App.js ]
import { useEffect, useState } from 'react';
import {ITEMS} from './constants';
import './App.css';
function App() {
const [tabValue, setTabValue] = useState('all');
const [list, setList] = useState(ITEMS);
// 버튼 값이 'all'에 해당하는 경우와 나머지에 대해서 비교하여 filter
useEffect(()=>{
if (tabValue === 'all') {
setList(ITEMS);
} else {
setList(ITEMS.filter((item) => item.communityCategoryCd === tabValue));
}
},[tabValue])
const onClickTab = (selectedTab) => {
setTabValue(selectedTab);
}
return (
<>
<div>
<input id="month_chk" type="checkbox" />
<label for="month_chk">이번 달</label>
</div>
<div>
<div className="tab-list">
<button className={tabValue === "all" ? "active" : ""} type="button" onClick={()=>onClickTab('all')}>전체</button>
<button className={tabValue === "all" ? "active" : ""} type="button" onClick={()=>onClickTab('01')}>01</button>
<button className={tabValue === "all" ? "active" : ""} type="button" onClick={()=>onClickTab('02')}>02</button>
<button className={tabValue === "all" ? "active" : ""} type="button" onClick={()=>onClickTab('03')}>03</button>
</div>
<div>
<ul>
{list.map((item) => (
<li key={item.communityContentSeq}>
<div>title: {item.title}</div>
<div>nickName: {item.nickName}</div>
<div>communityCategoryCd: {item.communityCategoryCd}</div>
</li>
))
}
</ul>
</div>
</div>
</>
);
}
export default App;
className={tabValue === "all" ? "active" : ""} 넣어서 버튼 클릭 시 활성화 스타일 적용
[ App.css ]
.tab-list button {
border: 1px solid #c1c1c1;
background-color: transparent;
width: 150px;
height: 35px;
border-radius: 3px;
}
// 버튼 활성화
.tab-list button.active {
background-color: #e1664b;
color: #fff;
}
📌 체크박스 (이번 달) 버튼 추가
- 체크박스 버튼 추가
- 현재 시간과 regDttm 값의 년도, 달을 비교해서 해당 달에 등록된 데이터만 필터링
[ App.js ]
import { useEffect, useState } from 'react';
import {ITEMS} from './constants';
import './App.css';
function App() {
const [tabValue, setTabValue] = useState('all');
const [list, setList] = useState(ITEMS);
const [showThisMonthOnly, setshowThisMonthOnly] = useState(false);
useEffect(()=> {
filterItems();
},[tabValue, showThisMonthOnly])
// 해당 탭에서 이번달에 해당하는 filter를 추가한 함수
const filterItems = () => {
let filteredItems = ITEMS;
// 버튼 값이 'all'이 아닌 나머지 버튼을 비교 filter
if (tabValue!== 'all') {
filteredItems = filteredItems.filter((item) => item.communityCategoryCd === tabValue);
}
// 현재 '년/월'값을 가져와서 만들어 놓은 constants.js 데이터에 있는 '년/월' 값을 비교하여 filter
if (showThisMonthOnly) {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth() + 1;
filteredItems = filteredItems.filter((item) => {
const regDate = item.regDttm.substring(0, 6);
const regYear = parseInt(regDate.substring(0, 4));
const regMonth = parseInt(regDate.substring(4, 6));
return regYear === currentYear && regMonth === currentMonth;
});
}
// 이 외 나머지 값 (여기서는 'all'에 해당됨)
setList(filteredItems);
}
const onClickTab = (selectedTab) => {
setTabValue(selectedTab);
}
// '이번 달' 체크박스 클릭하면 해당 탭에서 '이번 달'에 해당하는 데이터만 보여주기
// prev 현재 값에서 !prev(반대값)으로 변경
// setshowThisMonthOnly((prev) => !prev); 이 방법이 더 정확하지만
// 실무에서는 setshowThisMonthOnly(!showThisMonthOnly); 이거를 더 많이 씀
const toggleShowThisMonthOnly = () => {
setshowThisMonthOnly((prev) => !prev);
// === setshowThisMonthOnly(!showThisMonthOnly);
}
return (
<>
<div>
<input id="month_chk" type="checkbox" onChange={toggleShowThisMonthOnly} />
<label for="month_chk">이번 달</label>
</div>
<div>
<div className="tab-list">
<button className={tabValue === "all" ? "active" : ""} type="button" onClick={()=>onClickTab('all')}>전체</button>
<button className={tabValue === "01" ? "active" : ""} type="button" onClick={()=>onClickTab('01')}>01</button>
<button className={tabValue === "02" ? "active" : ""} type="button" onClick={()=>onClickTab('02')}>02</button>
<button className={tabValue === "03" ? "active" : ""} type="button" onClick={()=>onClickTab('03')}>03</button>
</div>
<div>
<ul>
{list.map((item) => (
<li key={item.communityContentSeq}>
<div>title: {item.title}</div>
<div>nickName: {item.nickName}</div>
<div>communityCategoryCd: {item.communityCategoryCd}</div>
</li>
))
}
</ul>
</div>
</div>
</>
);
}
export default App;
📌 검색 기능 추가
- 검색 input, button 추가
- useState 사용
[ App.js ]
import { useEffect, useState } from 'react';
import {ITEMS} from './constants';
import './App.css';
function App() {
const [tabValue, setTabValue] = useState('all');
const [list, setList] = useState(ITEMS);
const [showThisMonthOnly, setshowThisMonthOnly] = useState(false);
// 검색 useState 추가
const [search, setSearch] = useState('');
useEffect(()=>{
// console.log(tabValue);
// if (tabValue === 'all') {
// setList(ITEMS);
// } else {
// setList(ITEMS.filter((item) => item.communityCategoryCd === tabValue));
// }
filterItems();
},[tabValue, showThisMonthOnly])
const filterItems = () => {
let filteredItems = ITEMS;
if (tabValue!== 'all') {
filteredItems = filteredItems.filter((item) => item.communityCategoryCd === tabValue);
}
if (showThisMonthOnly) {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth() + 1;
filteredItems = filteredItems.filter((item) => {
const regDate = item.regDttm.substring(0, 6);
const regYear = parseInt(regDate.substring(0, 4));
const regMonth = parseInt(regDate.substring(4, 6));
return regYear === currentYear && regMonth === currentMonth;
});
}
// tab에서 filter가 된 이후에, 검색 기능 로직 타야하기 때문에 추가
// 검색어가 없을 때와 있을 때
if (search !== ""){
filterTitle(filteredItems)
// filteredItems = filteredItems.filter((item) => item.title.replace(" ", "").toLocaleLowerCase().includes(search.toLocaleLowerCase().replace(" ", "")))
}else{
setList(filteredItems);
}
}
const onClickTab = (selectedTab) => {
// console.log(e.target.value);
setTabValue(selectedTab);
}
const toggleShowThisMonthOnly = () => {
setshowThisMonthOnly((prev) => !prev);
// === setshowThisMonthOnly(!showThisMonthOnly);
}
const handleSearch = (e) => {
setSearch(e.target.value);
// console.log(search);
}
// 검색 기능 추가
// 검새겅가 있을 때와 없을때로 나누고, 검색어가 없는 상태에서 검색 버튼 클릭 시,
// 해당 탭을 클릭하면 해당 탭에 있는 내용이 보여야 한다.
// 중복되는 부분이 있어 보이지만, 탭 안엔서 이루어지는 기능이기 때문에 중복되는 부분이 있음
const filterTitle = (items) => {
if (search) {
setList(items.filter((item) => {
return (
item.title.toLocaleLowerCase().includes(search.toLocaleLowerCase()))
}))
} else {
if (tabValue !== 'all') {
setList(ITEMS.filter((item) => item.communityCategoryCd === tabValue));
} else {
setList(ITEMS);
}
}
}
return (
<>
<div>
<div>
<input type="text" value={search} onChange={handleSearch} />
<button type="button" onClick={()=>{filterTitle(list)}}>검색</button>
</div>
</div>
<div>
<input id="month_chk" type="checkbox" onChange={toggleShowThisMonthOnly} />
<label for="month_chk">이번 달</label>
</div>
<div>
<div className="tab-list">
<button className={tabValue === "all" ? "active" : ""} type="button" onClick={()=>onClickTab('all')}>전체</button>
<button className={tabValue === "01" ? "active" : ""} type="button" onClick={()=>onClickTab('01')}>01</button>
<button className={tabValue === "02" ? "active" : ""} type="button" onClick={()=>onClickTab('02')}>02</button>
<button className={tabValue === "03" ? "active" : ""} type="button" onClick={()=>onClickTab('03')}>03</button>
</div>
<div>
<ul>
{list.map((item) => (
<li key={item.communityContentSeq}>
<div>title: {item.title}</div>
<div>nickName: {item.nickName}</div>
<div>communityCategoryCd: {item.communityCategoryCd}</div>
<div>날짜: {item.regDttm}</div>
</li>
))
}
</ul>
</div>
</div>
</>
);
}
export default App;
'React' 카테고리의 다른 글
[React] 간단한 투두리스트(todolist) 만들기 (0) | 2024.05.24 |
---|---|
[React] 노마드 수업 1-state, setState 등 소스 (0) | 2022.07.23 |
[React] 노마드 수업 1- 소스 (0) | 2021.08.20 |
[React] 노마드 수업 1 (0) | 2021.08.20 |
[React] 설치 및 시작하기 - 노마드 수업 정리 (0) | 2021.08.20 |