
함수형 컴포넌트로
.map메서드 사용시 요소 한 개만 선택하기.
- 상수 데이터 기반의 포스팅인 점 참고해 주세요!
const [tagList] = useState(TAG_LIST);
const [, setChoiceTagID] = useState(1);
const [clickValue, setClickValue] = useState(false);
const [filterTag, setFilterTag] = useState([]);
const TAG_LIST = [
{ id: 1, tag_category: '업계연봉수준', color: 'rgb(246, 246, 246)' },
{ id: 2, tag_category: '투자', color: 'rgb(240, 248, 248)' },
{ id: 3, tag_category: '인원성장률', color: 'rgb(238, 237, 244)' },
{ id: 4, tag_category: '퇴사율', color: 'rgb(238, 245, 246)' },
{ id: 5, tag_category: '인원수', color: 'rgb(236, 249, 247)' },
{ id: 6, tag_category: '업력', color: 'rgb(239, 251, 243)' },
{ id: 7, tag_category: '보상', color: 'rgb(233, 231, 238)' },
{ id: 8, tag_category: '기업문화', color: 'rgb(240, 249, 245)' },
{ id: 9, tag_category: '가족', color: 'rgb(233, 244, 251)' },
{ id: 10, tag_category: '출퇴근', color: 'rgb(236, 241, 241)' },
];
tagList에 담아주었다.id를 기준으로 비교를 해 줄 것이다. 여기서 id는 인덱스 값이랑 맞춰주었다.choiceTagID : 특정한 데이터의 ID를 담아줄 stateclickValue : class가 꺼졌는지(false) 켜졌는지(true) 판별해줄 statefilterTag : 선택한 값만을 필터링할 때 담아줄 배열 state const clickTagBtn = id => {
setChoiceTagID(id);
setClickValue(!clickValue);
tagList[id].isChecked = !clickValue;
};
id를 인자로 받아온다.id를 choiceTagID state에 담는다.true <-> false를 반복해주는 setClickValue(!clickValue);id는 일부러 인덱스와 같게 해주었다. 이때 tagList의 인덱스로 접근하여, 키 isChecked의 값을 true 혹은 false으로 바꿔준다. <ul className="tagPickWrap">
{tagList.map(tag => (
<TagData key={tag.id} tagData={tag} clickTagBtn={clickTagBtn} />
))}
</ul>
<li> 요소를 컴포넌트화하여 map으로 돌렸다.// TagData.js
function TagData({ tagData, clickTagBtn }) {
return (
<li className="tags">
<button
className={`${tagData.isChecked ? 'tagBtn' : 'tagBtnOFF'}`}
style={{ backgroundColor: tagData.color }}
onClick={() => clickTagBtn(tagData.id)}
>
{tagData.tag_category}
</button>
</li>
);
}
true/false) 기준으로 클래스명 전환이 이루어진다.tagBtn는 선택되었다는 의미로 파란색 테두리를 주었다.<button>에 onClick 메서드를 달아 부모 컴포넌트의 함수를 실행하도록 한다. 이때 인자에 id를 넣고 같이 전달한다.// 변경 전
{
id: 3,
tag_category: '퇴사율',
color: 'rgb(238, 245, 246)',
isChecked: false,
}
// 변경 후
{
id: 3,
tag_category: '퇴사율',
color: 'rgb(238, 245, 246)',
isChecked: true,
}
filterTag를 빈 배열 state로 선언해 주었었다.filterTag에 선택된 태그만을 담을 것이고, filterTag에 선택된 태그들이 담겼으면 filterTag.map을 쓸 것이다. useEffect(() => {
setFilterTag(tagList.filter(tag => tag.isChecked === true));
}, [clickValue, tagList]);
💡 맨 처음에는 디펜덴시 없이, useEffect(()=>{}) 의 형태만을 써주었었다. 그랬더니 개발자도구에 보이는 건 백몇개씩 쌓이는 무한루프 error... 그래서 디펜덴시에 useEffect가 언제 쓰여서 언제 렌더링이 될 건지, 시점을 정해주어야 했다.
isChecked 속성이 true인 것만 필터링하여 filterTag state에 담아주었다.clickValue와 tagList가 변경될 때이다.clickValue : 태그 요소가 클릭될 때.tagList : 배열 중 true <-> false가 계속 바뀔 때.map<ul className="choiceTagList">
{filterTag.map(tag => (
<li className="choiceTags" key={tag.id}>
<button className="choiceTagBtn">{tag.tag_category}</button>
</li>
))}
</ul>
map 메서드로 돌려 주었다.true <-> false가 바뀔때마다 변경된다.function BodyTags() {
const [tagList] = useState(TAG_LIST);
const [, setChoiceTagID] = useState(1);
const [clickValue, setClickValue] = useState(false);
const [filterTag, setFilterTag] = useState([]);
const clickTagBtn = id => {
setChoiceTagID(id);
setClickValue(!clickValue);
tagList[id].isChecked = !clickValue;
};
useEffect(() => {
setFilterTag(tagList.filter(tag => tag.isChecked === true));
}, [clickValue, tagList]);
return (
<>
<div className="BodyTags">
<p className="TagText">
기업의 특별한 복지, 혜택 등 태그를 선택하여
<br />
나에게 꼭 맞는 포지션을 찾아보세요!
</p>
<div className="TagPick">
<p className="tagPickText">카테고리 선택</p>
<ul className="tagPickWrap">
{tagList.map(tag => (
<TagData key={tag.id} tagData={tag} clickTagBtn={clickTagBtn} />
))}
</ul>
<p className="tagPickText">선택된 태그</p>
<ul className="choiceTagList">
{filterTag.map(tag => (
<li className="choiceTags" key={tag.id}>
<button className="choiceTagBtn">{tag.tag_category}</button>
</li>
))}
</ul>
<p className="guideText">
해당 태그를 모두 만족하는 포지션이 노출됩니다.
</p>
</div>
</div>
<Footer />
</>
);
}
function TagData({ tagData, clickTagBtn }) {
return (
<li className="tags">
<button
className={`${tagData.isChecked ? 'tagBtn' : 'tagBtnOFF'}`}
style={{ backgroundColor: tagData.color }}
onClick={() => clickTagBtn(tagData.id)}
>
{tagData.tag_category}
</button>
</li>
);
}

📚 감사했던 참고 벨로그
https://velog.io/@ljo094822/react-map%ED%95%A8%EC%88%98-%EC%82%AC%EC%9A%A9%EC%8B%9C-%ED%81%B4%EB%A6%AD%EC%8B%9C-%EC%8A%A4%ED%83%80%EC%9D%BC-%EB%B0%94%EA%BE%B8%EA%B8%B0