접혔다 늘어났다 하는 아코디언처럼 클릭 이벤트가 발생할 때마다 접힌 내용이 펼쳐졌다가 접혀서 사라졌다가 하는 메뉴
팀 프로젝트로 요기요 클론코딩(을 빙자한 다 뜯어고치기)을 하면서 가장 기능이 많은 상세페이지를 맡은 이상 아코디언 메뉴는 필수!
각 카테고리별로 나뉘어진 메뉴를 클릭하면 해당 카테고리에 속하는 음식들을 보여주게 하고 다시 클릭하면 사라지게 해야 했는데, state
와 className
이면 아주 간단하게 구현이 가능했다.
하지만 한 가지 난관이 있었으니...
바로 기본값이 false
라서 기본적으로 다 닫혀 있는 아코디언 메뉴의 첫 번째 메뉴만 true
를 주고 열려 있게 하는 것이었다. 이것도 어차피 그냥 조건문과 state
만 해주면 되니까 아주 간단하게 해결삽가능!이라고 생각했는데 내 생각대로 됐으면 내가 이 글을 안 썼지...^^...
// 아코디언 메뉴에서 첫 번째 메뉴만 열려 있게 하는 코드를 짜보자
const [isCollapsed, setIsCollapsed] = useState(false);
const toggleCollapsingMenu = () => {
setIsCollapsed(!isCollapsed);
};
const firstMenu = useRef(null);
useEffect(() => {
if (firstMenu.current.id === 1) {
setIsCollapsed(true);
}
}, [id]);
코드 설명
처음 내가 짰던 코드에서는 카테고리 메뉴의 상태를 true
와 false
를 이용해서 관리하고 기본값으로는 false
를 줘서 모든 카테고리 메뉴가 기본적으로 다 닫혀 있도록 설정했다.
그리고 첫 번째 메뉴만 열려 있게 하기 위해서, 이미 각 카테고리 메뉴마다 id
를 갖고 있었기에 그걸로 첫 번째 메뉴를 useRef
로 직접 접근해서 id
가 1이면 state
인 isCollapsed
를 true
로 설정하도록 했다.
그런데 이게 제대로 작동하질 않았다...🙃
// 아코디언 메뉴에서 첫 번째 메뉴만 열려 있게 하는 코드를 짜보자
const [isCollapsed, setIsCollapsed] = useState(false);
const toggleCollapsingMenu = () => {
setIsCollapsed(!isCollapsed);
};
const firstMenu = useRef(null);
useEffect(() => {
if (firstMenu.current.id === '1') {
setIsCollapsed(true);
}
}, [id]);
해결 과정
console.log
만 제대로 좀 더 찍어봤으면 금방 해결했을 문제였다.
firstMenu.current.id
로 들어오는 값의 타입이 Number
가 아니라 String
이어서 생긴 문제였기 때문이다. 역시 프론트엔드는 디버깅할 때 무조건 console.log
부터 찍어봐야만 한다.
이런 간단한 문제를 들고 멘토님 찾아가서 질문하고 같이 코드를 보다가 멘토님이 타입 말씀하신 순간 내 실수를 깨닫고 바로 고쳤다ㅎ...
조금 부끄러운 순간이었지만 내색하지 않고 자연스럽게 넘어가는데 멘토님이 어차피 props
로 id
가 내려오는데 굳이 useRef
를 사용할 필요가 없지 않냐고 조금 더 효율적으로 리팩토링할 수 있게 도와주셨다.
const [isCollapsed, setIsCollapsed] = useState(false);
const toggleCollapsingMenu = () => {
setIsCollapsed(!isCollapsed);
};
useEffect(() => {
// 조건 상수화
const isFirstCategory = id === 1;
if (isFirstCategory) {
setIsCollapsed(true);
}
}, [id]);
리팩토링 과정
props
활용props
로 카테고리의 id
가 내려오고 있으므로 그것을 바로 활용useRef
를 사용하지 않아도 되므로 코드가 간결해진다