2025. 2. 16. 21:50ㆍ프론트엔드/REACT
📌 React에서 관심사(취미) 선택 모달 구현하기
💡 개요
React에서 사용자가 관심사(취미)를 선택할 수 있는 모달(InterestSelectModal)을 구현하는 과정에서 발생할 수 있는 문제와 해결 방법을 정리한 포스트입니다.
이 글에서는 Recoil 상태 관리, props 전달, 배열 데이터 업데이트, UI 반영 방식 등을 다룹니다.
🔹 1. 관심사 선택 모달의 핵심 기능
사용자가 관심사를 선택하면 배열 형태로 저장되며, 선택한 관심사는 다시 모달에서 표시됩니다.
이 과정에서 고려해야 할 사항:
- interests 데이터를 배열 형태로 유지해야 함 → ['헬스', '맛집 탐방'] 같은 형식
- 클릭하면 관심사가 추가/제거될 수 있어야 함
- 최대 10개까지만 선택 가능해야 함
- 선택된 항목은 UI에서 스타일 변경(배경색 등) 되어야 함
- 모달이 닫힐 때 데이터가 유지되어야 함
이 기능을 구현하기 위해 React의 상태 관리와 이벤트 핸들링을 활용합니다.
🔹 2. 관심사 선택 모달 구현 (InterestSelectModal.jsx)
📌 1) interests가 배열 형태인지 확인
사용자가 선택한 관심사를 저장하는 interests는 배열 형태여야 합니다.
예를 들어, 아래처럼 ['헬스', '맛집 탐방'] 형식으로 저장되어야 합니다.
const [interests, setInterests] = useState(["헬스", "맛집 탐방"]);
⚡ useState가 아닌 Recoil을 사용할 경우 useRecoilState(profileEditState)로 관리할 수 있습니다.
📌 2) 관심사 목록 필터링 (한글 검색 지원)
관심사 목록을 검색할 때 한글 초성 검색 기능을 적용하여, 사용자가 "ㅎㅅ"을 입력하면 "헬스"가 검색되도록 설정합니다.
const filteredHobbyData = hobbyData.map((category) => ({
...category,
hobbies: category.hobbies.filter((hobby) => {
const decomposedHobby = decomposeHangul(hobby.name);
const decomposedSearch = decomposeHangul(searchQuery);
return decomposedSearch.every((searchChar, index) => {
const hobbyChar = decomposedHobby[index];
if (!hobbyChar) return false;
if (decomposedSearch.length === 1) {
return hobbyChar.chosung === searchChar.chosung;
} else if (decomposedSearch.length === 2) {
return (
hobbyChar.chosung === searchChar.chosung &&
hobbyChar.jungsung === searchChar.jungsung
);
} else {
return (
hobbyChar.chosung === searchChar.chosung &&
hobbyChar.jungsung === searchChar.jungsung &&
hobbyChar.jongsung === searchChar.jongsung
);
}
});
}),
}));
✅ decomposeHangul 함수를 사용해 초성 검색이 가능하도록 구현
📌 3) 클릭하면 관심사 추가/제거 (최대 10개 제한)
사용자가 관심사를 클릭하면 interests 배열을 업데이트해야 합니다.
- 이미 선택된 경우 → 배열에서 제거
- 선택되지 않은 경우 → 배열에 추가 (최대 10개 제한)
const handleHobbyClick = (name) => {
const isAlreadySelected = interests.includes(name);
const updatedHobbies = isAlreadySelected
? interests.filter((hobby) => hobby !== name) // 이미 선택된 경우 제거
: interests.length < 10
? [...interests, name] // 최대 10개까지만 추가
: interests;
setInterests(updatedHobbies); // 새로운 배열로 업데이트
};
✅ setInterests를 사용해 배열을 직접 수정
✅ filter()를 사용해 이미 선택된 경우 삭제
✅ length < 10으로 최대 개수 제한
📌 4) 선택된 관심사 스타일 변경
UI에서 선택된 관심사는 배경색을 변경하여 사용자에게 피드백을 제공해야 합니다.
{category.hobbies.map((hobby, idx) => (
<div
key={idx}
className={`hobby-items ${interests.includes(hobby.name) ? "selected" : ""}`}
onClick={() => handleHobbyClick(hobby.name)}
>
<span className="hobby-emoji">
{hobby.emoji} {hobby.name}
</span>
</div>
))}
✅ interests.includes(hobby.name)이 true이면 "selected" 클래스를 추가
CSS 코드 (InterestSelectModal.css)
.hobby-items {
padding: 8px 12px;
border-radius: 10px;
cursor: pointer;
transition: 0.2s;
}
.hobby-items.selected {
background-color: #007aff;
color: white;
}
✅ 선택된 관심사는 파란색 배경 & 흰색 글씨로 변경
🔹 3. 관심사 선택 데이터를 ProfileEdit 페이지에 반영
사용자가 관심사를 선택하면 profile.interests에 반영되어야 합니다.
ProfileEdit 페이지에서 InterestSelectModal을 다음과 같이 사용합니다.
<InterestSelectModal
isOpen={isInterestModalOpen}
onClose={() => setIsInterestModalOpen(false)}
interests={profile.interests} // ✅ 배열로 전달
setInterests={(newInterests) => setProfile({ ...profile, interests: newInterests })} // ✅ 배열 유지
/>
✅ interests가 배열 형태로 유지됨
✅ setProfile()을 사용하여 profile.interests를 업데이트
🔹 4. 최종적으로 완성된 관심사 선택 기능
🎯 사용자가 관심사를 선택하면 UI에 반영되며, 모달을 닫았다가 다시 열어도 유지됩니다.
🎯 10개 이상 선택할 수 없도록 제한되며, 클릭하면 추가/삭제가 가능합니다.
🎯 한글 초성 검색이 지원되어 편리한 검색이 가능합니다.
'프론트엔드 > REACT' 카테고리의 다른 글
| React 관심사 선택 모달 개선하기 (3) | 2025.02.17 |
|---|---|
| React 모달에서 입력값을 "수정하기" 버튼을 눌러야 반영되도록 하기 (3) | 2025.02.17 |
| 📌 React에서 페이지네이션과 유효성 검사 구현하기 (0) | 2025.02.15 |
| 🚀 React에서 공지사항(Notice) 페이징 최적화 & 성능 개선하기 (1) | 2025.02.15 |
| 🚀 React Query를 사용하여 FAQ 관리 성능 개선하기 (0) | 2025.02.15 |