문제가 된 코드
const FollowPointer = () => {
const [cursorX, setCursorX] = useState(null);
const [cursorY, setCursorY] = useState(null);
// 마우스 커서 위치 기록
const mouseMoveHandler = (e) => {
console.log(cursorX, cursorY);
setCursorX(e.clientX);
setCursorY(e.clientY);
};
// 마우스 커서 위치 기록
useEffect(() => {
window.addEventListener("mousemove", mouseMoveHandler);
return () => window.removeEventListener("mousemove", mouseMoveHandler);
}, []);
return (
<div>
{cursorX} {cursorY}
</div>
);
};
export default FollowPointer;
문제
console.log(cursorX, cursorY)가 제대로 된 마우스의 좌표를 출력하지 못함
문제 원인
React의 라이프 사이클에 대한 이해
컴포넌트가 업데이트되면서 이벤트 핸들러가 재생성되면서 참조값이 변하고
useEffect로 부착한 이벤트 핸들러는 새로 생성된 이벤트 핸들러로 업데이트되지 못해서 발생한 문제
순서대로 과정을 정리하면
1. 컴포넌트가 마운트됨
2. mouseMoveHandler 이벤트 리스너 생성
3. mouseMoveHandler 이벤트 리스너가 useEffect를 사용해서 window 객체에 부착됨
4. 마우스가 움직임 -> mouseMoveHandler 이벤트 리스너는 cursorX, cursorY의 상태값을 업데이트
5. 상태가 업데이트되었으므로 컴포넌트 업데이트
6. 컴포넌트가 업데이트되면서 mouseMoveHandler 이벤트 리스너가 재생성
7. 기존의 mouseMoveHandler 이벤트 리스너는 window 객체에 부착되어 있는 상태로 남아있고
새로 선언된 mouseMoveHandler 이벤트 리스너는 window 객체에 부착되지 않음
8. 상태값이 변하면서 상태값의 참조주소도 변했으나 기존의 mouseMoveHandler 이벤트 리스너도
업데이트된 상태값의 주소를 알지 못하므로 변경된 상태값을 출력하지 못하고 초기에 읽어들인 상태값만을 계속해서 출력함
수정된 코드
import { useCallback, useState, useEffect } from "react";
const FollowPointer = () => {
const [cursorX, setCursorX] = useState(null);
const [cursorY, setCursorY] = useState(null);
// 마우스 커서 위치 기록
const mouseMoveHandler = useCallback(
(e) => {
console.log(cursorX, cursorY);
setCursorX(e.clientX);
setCursorY(e.clientY);
},
[cursorX, cursorY]
);
// 마우스 커서 위치 기록
useEffect(() => {
window.addEventListener("mousemove", mouseMoveHandler);
return () => window.removeEventListener("mousemove", mouseMoveHandler);
}, [mouseMoveHandler]);
return (
<div>
{cursorX} {cursorY}
</div>
);
};
export default FollowPointer;