Skip to content

Instantly share code, notes, and snippets.

@lebbe
Last active November 24, 2021 20:54
Show Gist options
  • Save lebbe/ef2f75b0fe6427f3d8f490c5f86872ce to your computer and use it in GitHub Desktop.
Save lebbe/ef2f75b0fe6427f3d8f490c5f86872ce to your computer and use it in GitHub Desktop.
A react hook for making draggable components
import { throttle } from 'lodash'
import { useEffect, useRef, useState } from 'react'
export type DraggableProps = {
onMouseDown: (e: React.MouseEvent) => void
style: { top: number; left: number }
}
export default function useDraggable(): DraggableProps {
const [mouseDown, setMouseDown] = useState(false)
const [top, setTop] = useState(20)
const [left, setLeft] = useState(20)
const deltaRef = useRef({ startTop: 0, startLeft: 0 })
useEffect(() => {
if (!mouseDown) return
function mouseMove(e: MouseEvent) {
setTop(Math.max(e.pageY - deltaRef.current.startTop, 0))
setLeft(Math.max(e.pageX - deltaRef.current.startLeft, 0))
}
function onMouseUp() {
setMouseDown(false)
}
const mouseMoveThrottle = throttle(mouseMove, 15)
document.addEventListener('mouseup', onMouseUp)
document.addEventListener('mousemove', mouseMoveThrottle)
return () => {
document.removeEventListener('mousemove', mouseMoveThrottle)
document.removeEventListener('mouseup', onMouseUp)
}
}, [mouseDown])
return {
onMouseDown: (e: React.MouseEvent) => {
deltaRef.current = {
startTop: e.pageY - top,
startLeft: e.pageX - left,
}
setMouseDown(true)
},
style: { top, left },
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment