@arcturus3/react-drag-drop v1.0.1
React Drag and Drop
Simple, flexible components and hooks for drag and drop in React.
Installation
npm i @arcturus3/react-drag-dropExamples
This library provides both components and hooks for drag and drop. The components encapsulate some common functionality and may be useful in simple cases or in addition to the hooks. If you need more control over drag and drop it should be fairly simple to implement this functionality yourself using the hooks. Following are two similar examples using each.
Components
import React from 'react';
import {Drag, Drop, DragView} from '@arcturus3/react-drag-drop';
export const Components = () => <>
<DragView onDrop={() => alert('dropped')} />
<Drag previewChildren>drag</Drag>
<br />
<Drop>drop</Drop>
</>;Hooks
import React from 'react';
import {useDrag, useDrop, useDragDrop} from '@arcturus3/react-drag-drop';
export const Hooks = () => {
const dragRef = useDrag();
const dropRef = useDrop();
const state = useDragDrop({
onDrop: () => alert('dropped')
});
const dragStyle = {
display: 'inline-block',
transform: state.dragging
? `translate(
${state.displacement!.x}px,
${state.displacement!.y}px
)`
: undefined
};
return <>
<span ref={dragRef} style={dragStyle}>drag</span>
<br />
<span ref={dropRef}>drop</span>
</>;
};Alternatives
React DnD
I think React DnD is based on some good ideas, but I wasn't a fan of its API, and the default HTML5 "backend" for mouse drag and drop comes with some of the limitations of native HTML5 drag and drop. I experienced performance issues with the only third party backend I could find. On the other hand, you may want to use React DnD if you need to support drag and drop with external types like files, links, and selected text.
React UseGesture
React UseGesture does not support drag and drop, but you may want to use it if you only need to support dragging elements and not interacting with drop elements. You could also use it for animating dragging while using this library to handle the drag and drop state.
Documentation
<Drag />
import {Drag} from '@arcturus3/react-drag-drop';A component that wraps its children with a drag element and prevents browser touch actions from interfering with dragging. Use with <DragView /> to display a drag preview and set the cursor style when hovering. It accepts the following props in addition to children.
previewChildren?: boolean(default:false): Whether to use children as the drag preview for<DragView />. Setting totruemodifiespayloadsuch that the value passed to thepayloadprop is stored inpayload.dataand the children are stored inpayload.previewfor use by<DragView />.payload?: any(default:undefined): SeeDragConfig.disabled?: boolean(default:false): SeeDragConfig.deps?: DependencyList(default:[]): SeeDragConfig.
<Drop />
import {Drop} from '@arcturus3/react-drag-drop';A component that wraps its children with a drop element. It accepts the following props in addition to children.
payload?: any(default:undefined): SeeDropConfig.disabled?: boolean(default:false): SeeDropConfig.deps?: DependencyList(default:[]): SeeDropConfig.
<DragView />
import {DragView} from '@arcturus3/react-drag-drop';A component that displays a preview of the element being dragged based on its payload and disables text selection while dragging. It's recommended to render this at the top of the component hierarchy so that it is always mounted. It accepts the following props.
preview?: (payload: any) => ReactNode(default: usespayload.previewif defined, which is set automatically ifpreviewChildren={true}on<Drag />components): Takes a drag payload and returns the preview to render. The preview could be calculated from the payload data or stored directly in the payload.hoverCursor?: string(default:''): Thecursorstyle to use while hovering over a<Drag />component before dragging starts.dragCursor?: string(default:''): Thecursorstyle to use while dragging.onDragStart?: Handler: SeeDragDropConfig.onDragMove?: Handler: SeeDragDropConfig.onDragEnd?: Handler: SeeDragDropConfig.onHoverStart?: Handler: SeeDragDropConfig.onHoverEnd?: Handler: SeeDragDropConfig.onDrop?: Handler: SeeDragDropConfig.onAny?: Handler: SeeDragDropConfig.deps?: DependencyList(default:[]): SeeDragDropConfig.
useDrag<T extends HTMLElement>(config)
import {useDrag} from '@arcturus3/react-drag-drop';Make a drag element.
config: DragConfig(default:{}): Configuration for the drag element. Note that ifconfigmay change when the component using this hook rerenders,config.depsshould be specified. Additionally, updates toconfigwill only be reflected inDragDropStateonce the next drag and drop event occurs.return: RefCallback<T>: A ref to assign to the element that should be draggable.
useDrop<T extends HTMLElement>(config)
import {useDrop} from '@arcturus3/react-drag-drop';Make a drop element.
config: DropConfig(default:{}): Configuration for the drop element. Note that ifconfigmay change when the component using this hook rerenders,config.depsshould be specified. Additionally, updates toconfigwill only be reflected inDragDropStateonce the next drag and drop event occurs.return: RefCallback<T>: A ref to assign to the element that should accept drag elements.
useDragDrop(config)
import {useDragDrop} from '@arcturus3/react-drag-drop';Get the drag and drop state and handle events.
config: DragDropConfig(default:{}): Configuration for state and event handlers.return: DragDropState: The drag and drop state, updated according toconfig.statePropsandrequestAnimationFrame.
DragConfig
Configuration object for drag elements with the following properties.
payload?: any(default:undefined): Data describing the drag element.disabled?: boolean(default:false): Whether to allow dragging the element. If set tofalsewhile dragging the element, this only takes effect once dragging ends normally.deps?: DependencyList(default:[]): Array containing the values of any variables that other properties ofDragConfigdepend upon. Used in the same manner as theuseEffectdependency list.
DropConfig
Configuration object for drop elements with the following properties.
payload?: any(default:undefined): Data describing the drop element.disabled?: boolean(default:false): Whether to allow dropping and hovering on the element.deps?: DependencyList(default:[]): Array containing the values of any variables that other properties ofDropConfigdepend upon. Used in the same manner as theuseEffectdependency list.
DragDropConfig
Configuration object for state and event handlers with the following properties.
onDragStart?: Handler: Pointer activates on a drag element.onDragMove?: Handler: Pointer moves after dragging has started.onDragEnd?: Handler: Pointer deactivates after dragging has started.onHoverStart?: Handler: Dragging is in progress and pointer moves over a drop element.onHoverEnd?: Handler: Dragging is in progress and pointer moves off a drop element.onDrop?: Handler: Dragging is in progress and pointer deactivates over a drop element.onAny?: Handler: Called on any of the other events inDragDropConfig.stateProps?: (keyof DragDropState)[](default: array of allDragDropStateproperties): Changes to theDragDropStatereturned byuseDragDropwill only cause a component to rerender if one of the properties in this array changes. If set, the array should contain all properties ofDragDropStatethat are used in the component, and serves as a performance optimization by ignoring those that aren't.deps?: DependencyList(default:[]): Array containing the values of any variables that other properties ofDragDropConfigdepend upon. Used in the same manner as theuseEffectdependency list.
Handler: (state, prevState) => void
Drag and drop event handler passed to DragDropConfig.
state: DragDropState: The drag and drop state after this event occurs. Note that foronDragEndandonDropin particular, this will be the initial state where nothing is being dragged, andprevStatemay be more useful.prevState: DragDropState: The drag and drop state before this event occurred.
DragDropState
Object containing the following properties.
dragging: boolean: Whether an element is being dragged.hovering: boolean: Whether the pointer is hovering a droppable element while dragging.dragPayload: any: Payload of the item being dragged orundefinedif not dragging.dropPayload: any: Payload of the item being hovered orundefinedif not dragginginitialPointerPosition: Point | null:pointerPositionwhen dragging started ornullif not dragging.pointerPosition: Point | null: Position of the pointer relative to the viewport ornullif not dragging. Addwindow.scrollXandwindow.scrollYto get the position relative to the document.initialElementPosition: Point | null:elementPositionwhen dragging started ornullif not dragging.elementPosition: Point | null:initialElementPositionplusdisplacementornullif not dragging.displacement: Point | null: Displacement betweeninitialPointerPositionandpointerPositionornullif not dragging.
Point
Object containing the following properties.
x: number: Horizontal coordinate of a position relative to the viewport.y: number: Vertical coordinate of a position relative to the viewport.