학습

react에서 addEventListener 사용시 문제

용사지둥 2021. 11. 15. 16:53
 useEffect(() => {
    window.addEventListener("wheel", handleMouseWheel, { passive: false });
    return () => {
      window.removeEventListener("wheel", handleMouseWheel, { passive: false });
    };
  }, []);

처음 렌더링 됐을 때 wheel에 이벤트로 handleMouseWheel 함수를 연결했다. 이 함수는 마우스 휠 움직임에 따라 스크롤바를 움직여주는 함수이다. 

 

const divFtop =
      divF.current.getBoundingClientRect().top +
      window.pageYOffset -
      100;

 

handleMouseWheel 함수 안에서 divF라는 전역변수를 사용하고 있다.  이  변수는 useRef()를 이용하여 해당 element에 접근 할 수 있게 해주는 변수다. 문제는 여기서 시작된다. 같은 component 내에 상위 컴포넌트에서 내려주는 props값의 변화에 따라 모달창을 보여주거나 보여주지 않는 함수를 작성했다. 

 

 {isModal ? <TotalModal /> : <Slide />}

isModal은 boolean 타입으로 작성되었다. false 일 경우에는 divF 변수에 접근할 수 있어서 handleMouseWheel 함수가 정상 작동한다. 하지만 isModal이 true 일 경우 <TotalModal /> 컴포넌트가 렌더링 되면서 containerEle가 useRef()로 접근할 element가 사라지게 되고 그 결과 다음과 같은 error를 겪게 되었다.

 

  이 문제를 해결하기 위해 처음 생각한 것은 isModal 이 true 상태일 때면 handleMouseWheel 함수 자체를 바로 return 시켜버려서 종료시키는 것이었다.

 

const handleMouseWheel = (e) => {
    if (isModal === true) return;
    .
    .
    .
    .
    .
}

위의 코드는 여전히 같은 error 상황이 발생했다. console.log로 isModal을 찍어봤을 때 false 상태에서 변하지 않는 것을 확인했다. 그런데 웃기게도 모달창은 열렸다.. 실제 컴포넌트 상에서는 true와 false로 바뀌지만 저 함수 내에서는 항상 초기값 false 상태였던 것이다.

 

 useEffect(() => {
    window.addEventListener("wheel", handleMouseWheel, { passive: false });
    return () => {
      window.removeEventListener("wheel", handleMouseWheel, { passive: false });
    };
  }, [isModal])

 문제를 해결한 코드는 위와 같다. isModal의 상태가 바뀔 때마다 useEffect를 실행시켜서 isModal 값이 바뀐 상태에서 handleMouseWheel 함수를 연결해 준 것이다. 자세한 원리는 알지 못하지만 이 코드로 추측하기로 addEventListener로 연결한 함수는 연결했을 당시의 state 값들을 그대로 사용하는 것 같다.