[React] 커스텀 훅 - useMouseLocation

이지현·2023년 9월 25일
1

react

목록 보기
1/3

들어가며

리액트를 사용할 때 커스텀 훅이라고 들어봤는데 직접 만들어 본 적은 아직 없습니다. 오늘 수업에서 실습으로 커스텀 훅 만들기를 하여 구현한 내용을 정리하려고 합니다!

본격적으로

저는 실습이 주어지면 코드 에디터를 사용하지 않고 채팅창이나 메모장에 적어보는 습관을 가지고 있습니다. 노트북이 디코와 줌과 코드 에디터까지 허용해주지 않아서 그런건 아닙니다. 그래서 이번에는 블로그를 작성하면서 하려고 합니다ㅎㅎ

훅의 기능

  • 현재 마우스 위치를 반환해줍니다.

필요한 이벤트

  • 현재 마우스 위치를 알려주는 이벤트가 필요합니다.
  • mousemove

참고한 사이트

https://codingbeautydev.com/blog/javascript-get-mouse-position/
https://codingbeautydev.com/blog/react-get-mouse-position/

실습하기

자바스크립트에서 마우스 위치를 알려주기 위해서 사용한 것은 clientXclientY이며, mousemove라는 이벤트를 사용하고 있습니다.

const mousePosText = document.getElementById('mouse-pos');
let mousePos = { x: undefined, y: undefined };

window.addEventListener('mousemove', (event) => {
  mousePos = { x: event.clientX, y: event.clientY };
  mousePosText.textContent = `(${mousePos.x}, ${mousePos.y})`;
});

마우스가 움직일 때마다 현재 위치를 알려주도록 한 코드로 보입니다.
이를 리액트 코드로 바꿔보도록 하겠습니다.

import {useState} from 'react';

function useMouseLocation({x, y}){
	const [mouseLocation, setMouseLocation] 
    	= useState({x: x, y: y} || {x: null, y: null});
  	const handleMouseMove = (event) => {
    	setMouseLocation({
          x: event.clientX + mouseLocation.x,
          y: event.clientY + mouseLocation.y
        });
    }
  	window.addEventListener('mousemove', handleMouseMove);
  	return mouseLocation;
}

기준점을 입력하지 않으면 기본적으로 null값 즉, 0, 0좌표를 기준으로 값을 설정합니다.

이 훅을 사용하면 문제가 있습니다. mousemove라는 이벤트가 발생할 때마다 계속 상태를 변경해서 리렌더링을 시킨다는 것입니다. 따라서 useEffect를 사용하여 다음과 같이 바꾸어주었습니다.

import {useState, useEffect} from 'react';

function useMouseLocation({x, y}){
	const [mouseLocation, setMouseLocation] 
    	= useState({x: x, y: y} || {x: null, y: null});
	useEffect(()=>{
    	const handleMouseMove = (event) => {
          setMouseLocation({
            x: event.x + mouseLocation.x,
            y: event.y + mouseLocation.y
          });
    	}
        
        window.addEventListener('mousemove', handleMouseMove);
      
      return () => {
      	window.removeEventListener('mousemove', handleMouseMove);
      }
    }, []);
  	
  	return mouseLocation;
}

export default useMouseLocation;

상태가 바뀔 때마다 리렌더링이 되는 것이 아니라 처음 렌더링 이후에만 실행할 수 있도록 하고, return값인 클린업 함수로 mousemove이벤트를 없애주었습니다.

tip: clientX는 x로 써도 됩니다. clientX의 축약 표현이 x - mdn

보통 MouseEvent같은 경우는 useEffect 내부에 적어서 클린업 함수를 사용하는 편이라고 합니다!

직접 사용해보기

import useMouseLocation from './Hooks/useMouseLocation';

function App() {
  	const mouseLocation = useMouseLocation();	
  
	return(
    	<div>
        	<div 
              style={{height: 100, width: 100,
            	backgroundColor: mouseLocation.x > 100 ? 'royalblue' : 'yellow' }}>
             </div>
        </div>
    )
}

export default App;

마우스 위치에 따라 div의 색상이 바뀌는 코드입니다!

결론

커스텀 훅으로 마우스 이벤트의 mousemove를 사용하여 직접 만들어보는 실습을 하였습니다. window 자체에 이벤트를 붙이는 경우엔 useEffect의 클린업 함수를 사용하여 이벤트를 별도로 관리해줄 수 있는 방법도 다양한 곳에서 활용이 가능할 듯 합니다.

profile
건축학도의 프론트엔드 개발자 되기

0개의 댓글