react에서 addEventListener 사용시 문제
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 값들을 그대로 사용하는 것 같다.