함수형 컴포넌트로
.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