Tang's
탕로그
Tang's
전체 방문자
오늘
어제
  • 분류 전체보기 (35)
    • FRONTEND (26)
      • JavaScript (6)
      • Algorithm (2)
      • CSS (2)
      • React (5)
      • Next.js (1)
      • 기타 (4)
      • 임시 (1)
      • 백만가지 ERROR (4)
      • 면접준비 (0)
      • project (1)
    • BACKEND (2)
      • Node.js (1)
      • MongoDB (1)
    • TODAY (7)
      • 생각 (1)
      • 회고 (6)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 개발자 회고
  • 신입 프론트엔드 개발자
  • 신입 프론트엔드 개발자 회고
  • nextjs metadata
  • jest nextjs typescript
  • React
  • Next.js 14
  • server action
  • nextjs ci/cd
  • 프론트엔드 개발자 회고
  • props와 state 차이점
  • partial prerendering
  • nginx-proxy-manager
  • docker-compose ci/cd
  • display:flex
  • jest 초기 세팅
  • Turbopack
  • jest recoil
  • Nextjs docker
  • jest react-query
  • ec2 권한 설정
  • linux 폴더 권한
  • modal 제어
  • jest
  • yarn create next-app
  • 회고
  • 폴더 권한 확인
  • 프론트엔드 면접질문
  • 폴더 권한 설정
  • 폴더 권한 변경

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Tang's

탕로그

[a-coha] 모달 창 상태 제어 문제
FRONTEND/project

[a-coha] 모달 창 상태 제어 문제

2023. 4. 27. 23:09

목표

원했던 구현은 해당 아이템을 클릭했을 때 모달창이 뜨고, 모달 창을 제외한 다른 곳을 클릭하면

모달 창이 사라지는 것.

 

문제 상황

처음 클릭 했을 때는 모달 창이 뜨지만 다른 곳을 클릭해도 모달 창이 닫히지 않는다.

모달 창의 open 과 close를 recoil boolean 상태값으로 관리했는데, 어째서인지 동작하지않는다.

 

// userList/index.tsx
...
const onClickHandler = (e:React.MouseEvent<HTMLDivElement>) => {
      setIsUserModalOpen(true);
  };

...
return (
    <div css={styles.userListBox}>
      <div css={styles.userListInnerBox}>
        {channelUsers &&
          channelUsers.map((member: ChannelUser, i: number) => {
            const isOnUser = onUser.some(
              (user) => user.userID === member.userId
            );
            const isAdmin = member.admin;
            return (
            // click 핸들러를 달아준 부분
              <div key={i} css={styles.user} onClick={onClickHandler}>
                <UserModal />
                <span css={styles.isUserOnline(isOnUser, isAdmin)}></span>
                <span css={styles.userName}>{member.name}</span>
                <span css={styles.adminCrown(isAdmin)}>
                  <FontAwesomeIcon
                    icon={faCrown}
                    style={{ color: '#ffbb00' }}
                  />
                </span>
              </div>
            );
          })}
      </div>
    </div>
    
//UserModal.tsx
...
const onClickHandler = (e:React.MouseEvent<HTMLDivElement>) => {
    console.log(isUserModalOpen);
      setIsUserModalOpen(false);
  };
...
  return (
    <div>
      <div
      	// 클릭하면 상태값이 false로 바뀌는 부분
        onClick={onClickHandler}
        css={styles.userModalBackground(isUserModalOpen)}
      ></div>
      <div
        css={styles.userModalTransition(isUserModalOpen)}
      >
        <div css={styles.userModalBox}>
          <div css={styles.userModalRightArrow}></div>
        </div>
      </div>
    </div>
  );
};

 

이유가 뭘까?

처음엔 UserModal 컴포넌트의 onClickHandler를 단 background 담당 부분이 z-index에 밀려서

클릭이 안되는 줄 알고 요리조리 살펴봤지만 background는 문제가 없었다.

 

그래서 처음 상태값을 true로 바꿔주는 onClickHandler를 달아주는 부분을 보니

// click 핸들러를 달아준 부분
              <div key={i} css={styles.user} onClick={onClickHandler}>
                <UserModal />
                ...

UserModal 컴포넌트가 자식으로 들어가기 때문에, UserModal 컴포넌트를 클릭해도 이벤트 버블링으로

해당 e.currentTarget인 div태그의 값으로만 계속 실행되는 것 같았다.

실제로 console로 출력해보니

계속해서 true 값이 찍혔다.

컴포넌트를 부모 - 자식 관계로 두지말고 독립적으로 로직을 바꿀까도 생각해봤지만,

map을 돌려서 나온 해당 user의 바로 왼쪽에 모달을 띄우고 싶어서 css position을 적용해논 터라

유지하기로 하고, 이벤트 버블링을 막는 방법을 찾아보기로 했다.

 

문제 해결

stopPropagation()

이라는 메서드가 유효했다.!

해당 메서드는 부모에게서 전파되는 이벤트를 막는다.

기존 코드에 아래와 같이 적용했다.

 

//UserModal.tsx
const onClickHandler = (e:React.MouseEvent<HTMLDivElement>) => {
    e.stopPropagation();
    setIsUserModalOpen(false);
  };

딱 한 줄 코드를 추가함으로써 문제가 해결됐다.!

이 메서드는 앞으로 다른곳에서도 유횽하게 자주 써먹을 수 있을 것 같다.

 

결과

 

    Tang's
    Tang's
    탕탕한 탕진의 기술 블로그!

    티스토리툴바