
우선 내가 만들 기능은 하트 버튼 클릭 시 좋아요가 눌리는 기능이다.
전체적인 구성을 보면 일단 구조가 같은 형태의 UI가 반복이 되고 있기 때문에 이 역시 map 메서드를 통해 코드를 간략화하였다.
const populars = [
{ title : "0", intro : "", number : "" },
{ title : "1", intro : "", number : "" },
{ title : "2", intro : "", number : "" },
{ title : "3", intro : "", number : "" },
{ title : "4", intro : "", number : "" },
{ title : "5", intro : "", number : "" },
{ title : "6", intro : "", number : "" },
{ title : "7", intro : "", number : "" },
]
<div className='main_circle_cont'>
{ populars.map((popular, index) => (
<div className='main_row_01'
key={index}>
<h4>{popular.title}</h4>
<p className='circle_intro'>{popular.intro}</p>
<p className='people_num'><img src= {peopleIcon} alt="인원수" />{popular.number}</p>
<button className='like_circle'>
<img src={} alt="찜하기"/>
</button>
</div>
))}
</div>
위와 같이 작성하면 코드가 훨씬 간결해지고 유지보수도 용이해진다.
그리고 버튼 안에 onClick 으로 해당 써클 클릭 시 하트가 눌리는 기능을 구현했다.
import unLikeIcon from '../images/favorite_stroke_black_icon.svg'
import likeIcon from '../images/favorite_black_icon.svg'
const [ likedPopular, setLikedPopular ] = useState(unLikeIcon);
const handleFavorite = (circle) => {
setLikedPopular(isLike === unLikeIcon ? likeIcon : unLikeIcon);
}
<div className='main_circle_cont'>
{ populars.map((popular, index) => (
<div className='main_row_01'
key={index}>
<h4>{popular.title}</h4>
<p className='circle_intro'>{popular.intro}</p>
<p className='people_num'><img src= {peopleIcon} alt="인원수" />{popular.number}</p>
<button className='like_circle'>
<img src={likedPopular} alt="찜하기"
onClick={()=>{handleFavorite(circle)}}/>
</button>
</div>
))}
</div>

문제점 : 이렇게 코드를 구성하면 각각의 컴포넌트가 아니라 전체 컴포넌트가 동시에 관리되기 때문에 하나의 ui에 좋아요를 누르면 모든 컴포넌트에 반영된다.
주요 키워드
const [likedPopular, setLikedPopular] = useState({});
< 객체 안의 상태 >
{
"enhypen": true, // 좋아요 누름
"bts": false, // 좋아요 안 누름
}
const handleFavorite = (circleTitle) => {
setLikedCircles(prev => ({
...prev,
[circleTitle]: !prev[circleTitle]
}));
};
prev = {
"enhypen": true,
"bts": false
}
결과
{
"enhypen": true,
"bts": true // ← 값만 바뀐 거!
}
⭐⭐ ...prev는 전개 연산자로 기존 데이터를 유지한 채, 특정 항목만 덮어쓰기(업데이트)하는데 사용됨 , 리액트에서 상태를 안전하게 업데이트할 때 아주 자주 쓰이는 패턴이기 때문에 알아둘것!
setIs(!is) // 단일 패턴 토글 시 사용
[circleTitle]: !prev[circleTitle] // 여러 개의 패턴 토글 시 사용
⭐⭐ 객체 상태에서 특정 key만 동적으로 업데이트할 때 사용
{circles.map((circle, index) => (
<div className='main_row_01' key={index}>
<div>
<h4>{circle.title}</h4>
<p className='circle_intro'>{circle.intro}</p>
<p className='people_num'><img src={peopleIcon} alt="인원수" />{circle.number}</p>
<button className='like_circle' onClick={() => handleFavorite(circle.title)}> // 타이틀명을 기준으로 true / false를 구분하기 때문에 인자로 전달
<img
src={likedCircles[circle.title] ? likeIcon : unLikeIcon}
// 객체에서 변수를 키로 접근할 때 []대괄호 사용
alt="찜하기"
/>
</button>
</div>
</div>
))}
