ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React / 에러 핸들링] Modal컴포넌트 만들기
    React 2022. 2. 8. 02:30

    모달 컴포넌트 스크롤을 막으면서 발생한 문제에 대한 기록입니다.

     

    첫 번째 문제

    e.preventDefault()와 e.stopPropagation()을 통해 이벤트를 막는 방법으로 스크롤을 막아야겠다는 생각을 했습니다.

    하지만 어림도 없이 스크롤은 잘 되었습니다.

    고민을 하다 실행 시점에서의 문제가 있다는 것을 깨닫게 되었습니다.

    mdn한글 문서를 보게 된다면 scroll은 view나 element가 스크롤될 때 scroll이벤트가 발생한다라고 되어있습니다.

    정말 모호한 말이 아닐 수가 없습니다. 영어로 된 mdn을 보게 된다면 scroll event라고 명시가 되었는데, The scrollevent fires when an element has been scrolled. 즉, 요소가 스크롤된 다음 이벤트가 발생한다.라고 명시되어 있습니다. 때문에 이미 스크롤이 일어난 곳에서 이벤트를 막아봤자 동작하지 않았던 것입니다.

     

    따라서 계속 scroll을 대체할 만한 이벤트를 찾던 와중 wheel과 mousewheel을 발견하게 됩니다.

    mousewheel의 경우 비표준이며 지원하지 않는 브라우저도 있으며, deprecated 되었다고 합니다.

    이에 따라 대체된 것이 wheel이벤트입니다.

    wheel이벤트를 본다면 Thewheelevent fires when the user rotates a wheel button on a pointing device (typically a mouse). 즉, 사용자가 휠 버튼을 돌릴 때 발생한다고 합니다.

    따라서 wheel이벤트에 이벤트 전파를 방지하고, 기본 동작을 막는다면, 잘 동작하게 됩니다.

     

     

    두 번째 문제

    하지만 이렇게 하다 보니 휠 이벤트 자체를 막게 되었고, Modal컴포넌트에서 overflow가 발생했을 때도 scroll이 되지 않았습니다.

    따라서 결국 body에 overflow:hidden속성을 주는 것으로 해결을 했습니다.

    또한 touch-action:none을 한다면 모바일에서도 막을 수 있습니다.

     

     

    세 번째 문제

    하지만 모바일의 특징상 끝까지 아래로 내린다면 url창이 보이며 위로 올리면 hidden이 되었던 요소들이 보이게 됩니다.

    저는 모달의 Dim에 height:100vh와 background색을 변경하였는데, 끝까지 overflow 된 모달을 위로 스크롤한다면 화면에서 숨겨져 있던 여백이 흰색으로 보이게 됩니다.

    따라서 모달의 height를  100%로 수정하여 추가적인 여백이 위로 올라오더라도 background색이 변하도록 했습니다.

     

    결론

    overflow는 reflow를 일으키기 때문에 이벤트로 막으려고 했지만...  복잡도를 생각했을 때 이것이 최선의 방법인것 같습니다.

    overflow로 인해 성능적 이슈가 발생하면 다른 방법을 다시 생각해보아야할것 같습니다.

     

    크롬 / Safari  web/mobile에서 잘 동작하는 것을 확인할 수 있습니다.

      useEffect(() => {
        document.body.style.overflow = 'hidden';
        return () => {
          document.body.style.overflow = 'auto';
        };
      }, []);

    별도로 빼두어 훅으로 사용할 수도 있습니다.

     

    참고

    https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event

    https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll_event

    https://developer.mozilla.org/en-US/docs/Web/API/Element/mousewheel_event

    댓글

Designed by Tistory.