프로그래밍/JavaScript

[JS] switch case 문과 비교 연산자(==, ===)

choar 2022. 8. 4. 20:49
반응형

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

반응형