React 프로젝트를 하다가 다음과 같은 오류가 있었다.
동영상을 재생해보면 사이드바(왼쪽)와 내용(오른쪽)의 연결이 이상한 것을 확인할 수 있다.
페이지 구조는 위와 같다.
chosenIndex는 DashBoard 컴포넌트의 state이다.
SideBar의 메뉴를 클릭하면 setChosenIndex가 작동하도록 되어 있어, 그 메뉴에 해당하는 내용을 보여주는 getSideBarContent(chosenIndex)의 리턴값이 적절히 바뀌어야 하는데, 적절히 바뀌지 않았다.
맨 처음에만 상품 목록이 제대로 표시되었고, 메뉴 버튼을 누르면 각각에 맞는 내용이 표시되어야 했는데 흰 화면만 떴다.
수정 전 코드를 살펴보자. (관련 있는 코드만 남겨두었다.)
// DashBoard.js
export const Dashboard = () => {
const [chosenIndex, setChosenIndex] = useState(1);
const onMenuClick = (e) => {
setChosenIndex(e.target.dataset.index);
};
const getSideBarContent = (index) => {
switch (index) {
case 1:
return <SellerProducts products={data.results} />;
case 2:
case 3:
case 4:
case 5:
return <div>준비중입니다.</div>;
}
};
return (
<Container>
<Title>
// 생략
</Title>
<Content>
<SideBar
chosenIndex={chosenIndex}
onMenuClick={onMenuClick}
productCount={data.count}
/>
{getSideBarContent(chosenIndex)}
</Content>
</Container>
);
};
// SideBar.js
export const SideBar = ({ chosenIndex, productCount, onMenuClick }) => {
const barMenus = [
{ index: 1, title: `판매중인 상품 (${productCount})` },
{ index: 2, title: '주문/배송', num: 2 },
{ index: 3, title: '문의/리뷰', num: 1 },
{ index: 4, title: '통계' },
{ index: 5, title: '스토어 설정' },
];
return (
<Container chosenIndex={chosenIndex}>
{barMenus.map((menu) => (
<Button
key={`barMenu_${menu.index}`}
num={menu.num}
data-index={menu.index}
onClick={onMenuClick}
>
{menu.title}
</Button>
))}
</Container>
);
};
const Container = styled.section`
// 생략
button {
color: #000000;
background-color: #ffffff;
&:hover {
background-color: #effff3;
}
&:nth-child(${({ chosenIndex }) => chosenIndex}) {
color: #ffffff;
background-color: #21bf48;
}
}
`;
얼핏 보면 문제가 없어보인다.
일단 메뉴 버튼을 눌렀을 때 색상이 변하기 때문에 onMenuClick이 작동하긴 한다는 것을 알 수 있다.
onMenuClick에 console.log를 넣어 확인하니 e.target.dataset.index의 type이 string인 것을 알 수 있었다.
그래서 코드를 다음과 같이 수정하니 제대로 동작했다.
// X
const onMenuClick = (e) => {
setChosenIndex(e.target.dataset.index);
};
// O
const onMenuClick = (e) => {
setChosenIndex(Number(e.target.dataset.index));
};
이전과 같이 코드를 짰을 때 chosenIndex가 switch case문에 걸리지 않은 이유는, switch case문은 switch 뒤 괄호에 들어가는 인자와 case 뒤에 나오는 값을 strictly equal(===)로 비교하기 때문이다. (ECMAScript-262 스펙을 참고했다.)
- a === b가 true려면(strictly equal) a, b의 값과 타입이 같아야 하고,
- a == b가 true려면(equal) a, b의 타입이 달라도 변환했을 때 값이 같으면 된다.
그래서 chosenIndex가 string일 때 switch case 문 어디에도 걸리지 못해 undefined가 리턴되고, 흰 화면만 떴던 것이다.
const getSideBarContent = (index) => {
switch (index) {
case 1:
return <SellerProducts products={data.results} />;
case 2:
case 3:
case 4:
case 5:
return <div>준비중입니다.</div>;
// 다음과 같이 default를 추가해 디버깅했어도 문제를 해결할 수 있었을 것이다.
default:
console.log(index);
console.log(typeof index);
return <div>default</div>;
}
};
문제를 해결한 모습은 다음과 같다.
References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality
https://tc39.es/ecma262/#sec-runtime-semantics-caseclauseisselected
'프로그래밍 > JavaScript' 카테고리의 다른 글
자바스크립트 비동기를 제대로 이해해보자 | async, await (0) | 2022.09.16 |
---|---|
[JS] 파일과 데이터를 모두 body에 넣어 API 요청하기 | form 태그 활용기 (2) (0) | 2022.08.30 |
[JS] Array 내장 메소드 reduce를 직접 구현해보자 (0) | 2022.06.12 |
[JS, Phaser 3] 자바스크립트로 게임 개발하기 | 뱀파이어 서바이벌 클론코딩 (2) | 2022.06.07 |
[JS] 객체 프로퍼티 접근법과 식별자 네이밍 규칙 (0) | 2022.04.26 |