react-draggable

repository·master·Indexed 27 days ago

https://github.com/react-grid-layout/react-draggable

A React component for making elements draggable using CSS transforms. It provides the <Draggable> component for standard use and <DraggableCore> for advanced control without automatic state or style management. Version 4.7.0 supports controlled positioning, custom drag handles, snapping grids, and nodeRef implementation to avoid ReactDOM.findDOMNode() deprecation warnings in React Strict Mode and React 19+.

Tokens
3.6K
Snippets
12
Records
18
Agent score
94%

What's inside react-draggable

  1. Quick Start with Draggable

    master

    Wrap an element with <Draggable> to make it movable. To avoid React Strict Mode warnings, always use the nodeRef prop and pass it to the child element.

    import React, { useRef } from 'react';
    import Draggable from 'react-draggable';
    
    function App() {
      const nodeRef = useRef(null);
    
      return (
        <Draggable nodeRef={nodeRef}>
          <div ref={nodeRef}>Drag me!</div
        </Draggable>
      );
    }
  2. Import react-draggable

    master

    Import the components using ES Modules or CommonJS depending on your project configuration.

    // ES Modules
    import Draggable from 'react-draggable';
    import { DraggableCore } from 'react-draggable';
    
    // CommonJS
    const Draggable = require('react-draggable');
    const { DraggableCore } = require('react-draggable');
  3. Implement nodeRef for React Strict Mode

    master

    To avoid ReactDOM.findDOMNode() deprecation warnings in React Strict Mode, pass a nodeRef prop to <Draggable> and attach the same ref to the child element. For custom components, ensure you use forwardRef to pass the ref down.

    // For custom components
    const MyComponent = forwardRef((props, ref) => (
      <div {...props} ref={ref}>Draggable content</div
    ));
    
    function App() {
      const nodeRef = useRef(null);
    
      return (
        <Draggable nodeRef={nodeRef}>
          <MyComponent ref={nodeRef} />
        </Draggable>
      );
    }
  4. Provide a nodeRef to avoid React 19 warnings

    master

    In React 19 and later, ReactDOM.findDOMNode() is no longer available. To ensure <DraggableCore> works correctly and to avoid console warnings, you must pass a nodeRef that points to the actual child DOM node.

    function MyComponent() {
      const nodeRef = React.useRef(null);
      return (
        <DraggableCore nodeRef={nodeRef}>
          <div ref={nodeRef}>Example Target</div>
        </DraggableCore>
      );
    }
    function MyComponent() {
      const nodeRef = React.useRef(null);
      return (
        <DraggableCore nodeRef={nodeRef}>
          <div ref={nodeRef}>Example Target</div
        </DraggableCore>
      );
    }
  5. Configure Content Security Policy (CSP)

    master

    By default, react-draggable injects a <style> element to prevent text selection during drags. If your CSP forbids 'unsafe-inline', you have three options:

    1. Pass a nonce: Provide the same nonce used in your CSP header to the nonce prop.
    2. Use Webpack: If no nonce is provided, the library falls back to Webpack's __webpack_nonce__ global.
    3. Opt out: Set enableUserSelectHack={false} and manually add selection rules to your own CSP-compliant stylesheet.
    // Option 1: Pass a nonce
    <Draggable nonce={cspNonce}>
      <div>Drag me</div
    </Draggable>
  6. Control <Draggable> position programmatically

    master

    While <Draggable> manages its own state, you can implement a controlled pattern by passing the position prop. This allows you to reset or move the element via external state.

    function ControlledDraggable() {
      const nodeRef = useRef(null);
      const [position, setPosition] = useState({ x: 0, y: 0 });
    
      const handleDrag = (e, data) => {
        setPosition({ x: data.x, y: data.y });
      };
    
      const resetPosition = () => setPosition({ x: 0, y: 0 });
    
      return (
        <>
          <button onClick={resetPosition}>Reset</button>
          <Draggable nodeRef={nodeRef} position={position} onDrag={handleDrag}>
            <div ref={nodeRef}>Drag me or reset!</div
          </Draggable>
        </>
      );
    }
  7. Use the <Draggable> component

    master

    The <Draggable> component wraps an existing element and extends it with event handlers and styles using CSS Transforms. It does not create a wrapper element in the DOM.

    Note: Do not set className, style, or transform on the <Draggable> component itself; set them on the child element instead. If the child already has a CSS Transform, wrap it in an intermediate <span>.

  8. Reference: <Draggable> Props

    master

    Available props for the <Draggable> component.

    ```ts
    type DraggableEventHandler = (e: Event, data: DraggableData) => void | false;
    
    type DraggableData = {
      node: HTMLElement,
      x: number, y: number,
      deltaX: number, deltaY: number,
      lastX: number, lastY: number,
    };
    PropTypeDefaultDescription
    allowAnyClickbooleanfalseAllow dragging on non-left-button clicks
    allowMobileScrollbooleanfalseDon't prevent touchstart, allowing scrolling inside containers
    axis'both' | 'x' | 'y' | 'none''both'Axis to allow dragging on
    boundsobject | string-Restrict movement. Use 'parent', a CSS selector, or {left, top, right, bottom}
    cancelstring-CSS selector for elements that should not initiate drag
    defaultClassNamestring'react-draggable'Class name applied to the element
    defaultClassNameDraggingstring'react-draggable-dragging'Class name applied while dragging
    defaultClassNameDraggedstring'react-draggable-dragged'Class name applied after drag
    defaultPosition{x: number, y: number}{x: 0, y: 0}Starting position
    disabledbooleanfalseDisable dragging
    enableUserSelectHackbooleantrueAdd user-select: none while dragging
    grid[number, number]-Snap to grid [x, y]
    handlestring-CSS selector for the drag handle
    nodeRefReact.RefObject-Ref to the DOM element. Required for React Strict Mode
    noncestring-CSP nonce for the injected user-select <style> element
    offsetParentHTMLElement-Custom offsetParent for drag calculations
    onDragDraggableEventHandler-Called while dragging
    onMouseDown(e: MouseEvent) => void-Called on mouse down
    onStartDraggableEventHandler-Called when dragging starts. Return false to cancel
    onStopDraggableEventHandler-Called when dragging stops
    position{x: number, y: number}-Controlled position
    positionOffset{x: number | string, y: number | string}-Position offset (supports percentages)
    scalenumber1Scale factor for dragging inside transformed parents
  9. Use <DraggableCore> for advanced dragging control

    master

    <DraggableCore> is an advanced component for users who need more control than the standard <Draggable> component provides. It maintains minimal internal state, making it suitable for integration with libraries that require fine-grained control over the draggable element.

    Note: <DraggableCore> requires exactly one child element. It clones this child and injects necessary event handlers.