리액트를 사용할 때 커스텀 훅이라고 들어봤는데 직접 만들어 본 적은 아직 없습니다. 오늘 수업에서 실습으로 커스텀 훅 만들기를 하여 구현한 내용을 정리하려고 합니다!
저는 실습이 주어지면 코드 에디터를 사용하지 않고 채팅창이나 메모장에 적어보는 습관을 가지고 있습니다. 노트북이 디코와 줌과 코드 에디터까지 허용해주지 않아서 그런건 아닙니다. 그래서 이번에는 블로그를 작성하면서 하려고 합니다ㅎㅎ
mousemove
https://codingbeautydev.com/blog/javascript-get-mouse-position/
https://codingbeautydev.com/blog/react-get-mouse-position/
자바스크립트에서 마우스 위치를 알려주기 위해서 사용한 것은 clientX
와 clientY
이며, 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
의 클린업 함수를 사용하여 이벤트를 별도로 관리해줄 수 있는 방법도 다양한 곳에서 활용이 가능할 듯 합니다.