Skip to main content

Draggable Types

Complete type definitions for draggable components and hooks.

Enums

DraggableState

Represents the different states a draggable item can be in.

enum DraggableState {
/** Item is at rest in its original or dropped position */
IDLE = "IDLE",
/** Item is currently being dragged by the user */
DRAGGING = "DRAGGING",
/** Item has been successfully dropped on a valid drop zone */
DROPPED = "DROPPED",
}

Usage Example

import { DraggableState } from 'react-native-reanimated-dnd';

const handleStateChange = (state: DraggableState) => {
switch (state) {
case DraggableState.IDLE:
console.log('Item is at rest');
break;
case DraggableState.DRAGGING:
console.log('Item is being dragged');
break;
case DraggableState.DROPPED:
console.log('Item was successfully dropped');
break;
}
};

Type Aliases

AnimationFunction

Custom animation function type for controlling how draggable items animate.

type AnimationFunction = (toValue: number) => number;

Parameters

  • toValue (number): The target value to animate to

Returns

  • number: The animated value (typically from withSpring, withTiming, etc.)

Example

import { withTiming, Easing } from 'react-native-reanimated';

const customAnimation: AnimationFunction = (toValue) => {
'worklet';
return withTiming(toValue, {
duration: 500,
easing: Easing.bounce
});
};

CollisionAlgorithm

Collision detection algorithms for determining when a draggable overlaps with a droppable.

type CollisionAlgorithm = "center" | "intersect" | "contain";

Values

  • center: Collision detected when the center point of the draggable is over the droppable
  • intersect: Collision detected when any part of the draggable overlaps with the droppable (default)
  • contain: Collision detected when the entire draggable is contained within the droppable

Usage Examples

// For precise dropping, use center collision
const preciseDraggable = useDraggable({
data: myData,
collisionAlgorithm: 'center'
});

// For easy dropping, use intersect (default)
const easyDraggable = useDraggable({
data: myData,
collisionAlgorithm: 'intersect'
});

// For strict containment, use contain
const strictDraggable = useDraggable({
data: myData,
collisionAlgorithm: 'contain'
});

Interfaces

UseDraggableOptions<TData>

Configuration options for the useDraggable hook.

interface UseDraggableOptions<TData = unknown> {
data: TData;
draggableId?: string;
dragDisabled?: boolean;
onDragStart?: (data: TData) => void;
onDragEnd?: (data: TData) => void;
onDragging?: (payload: DraggingPayload<TData>) => void;
onStateChange?: (state: DraggableState) => void;
animationFunction?: AnimationFunction;
dragBoundsRef?: React.RefObject<Animated.View | View>;
dragAxis?: "x" | "y" | "both";
collisionAlgorithm?: CollisionAlgorithm;
children?: React.ReactNode;
handleComponent?: React.ComponentType<any>;
}

Properties

data
  • Type: TData
  • Required: Yes
  • Description: Data payload associated with this draggable item. This data is passed to drop handlers when the item is successfully dropped.
const data = { id: '1', name: 'Task 1', priority: 'high' };
draggableId
  • Type: string
  • Required: No
  • Description: Unique identifier for this draggable item. If not provided, one will be generated automatically.
dragDisabled
  • Type: boolean
  • Default: false
  • Description: Whether dragging is disabled for this item. When true, the item cannot be dragged.
onDragStart
  • Type: (data: TData) => void
  • Required: No
  • Description: Callback fired when dragging starts.
const handleDragStart = (data) => {
console.log('Started dragging:', data.name);
setIsDragging(true);
};
onDragEnd
  • Type: (data: TData) => void
  • Required: No
  • Description: Callback fired when dragging ends (regardless of whether it was dropped successfully).
const handleDragEnd = (data) => {
console.log('Finished dragging:', data.name);
setIsDragging(false);
};
onDragging
  • Type: (payload: DraggingPayload<TData>) => void
  • Required: No
  • Description: Callback fired continuously while dragging. Useful for real-time feedback.
const handleDragging = ({ x, y, tx, ty, itemData }) => {
const currentX = x + tx;
const currentY = y + ty;
console.log(`${itemData.name} is at (${currentX}, ${currentY})`);
};
onStateChange
  • Type: (state: DraggableState) => void
  • Required: No
  • Description: Callback fired when the draggable state changes.
const handleStateChange = (state) => {
if (state === DraggableState.DROPPED) {
showSuccessMessage();
}
};
animationFunction
  • Type: AnimationFunction
  • Required: No
  • Description: Custom animation function for controlling how the item animates when dropped. If not provided, uses default spring animation.
const bounceAnimation = (toValue) => {
'worklet';
return withTiming(toValue, {
duration: 600,
easing: Easing.bounce
});
};
dragBoundsRef
  • Type: React.RefObject<Animated.View | View>
  • Required: No
  • Description: Reference to a View that defines the dragging boundaries. The draggable item will be constrained within this view's bounds.
const boundsRef = useRef<View>(null);

return (
<View ref={boundsRef} style={styles.container}>
<Draggable dragBoundsRef={boundsRef} data={data}>
<Text>Bounded draggable</Text>
</Draggable>
</View>
);
dragAxis
  • Type: "x" | "y" | "both"
  • Default: "both"
  • Description: Constrains dragging to a specific axis.
// Horizontal slider
const horizontalDraggable = useDraggable({
data: sliderData,
dragAxis: 'x'
});

// Vertical slider
const verticalDraggable = useDraggable({
data: sliderData,
dragAxis: 'y'
});
collisionAlgorithm
  • Type: CollisionAlgorithm
  • Default: "intersect"
  • Description: Algorithm used for collision detection with drop zones.

UseDraggableReturn

Return value from the useDraggable hook.

interface UseDraggableReturn {
animatedViewProps: {
style: AnimatedStyle<ViewStyle>;
onLayout: (event: LayoutChangeEvent) => void;
};
gesture: GestureType;
state: DraggableState;
animatedViewRef: ReturnType<typeof useAnimatedRef<Animated.View>>;
hasHandle: boolean;
}

Properties

animatedViewProps
  • Type: { style: AnimatedStyle<ViewStyle>; onLayout: (event: LayoutChangeEvent) => void; }
  • Description: Props to spread on the animated view that will be draggable. Contains the animated style and layout handler.
gesture
  • Type: GestureType
  • Description: Gesture object to attach to GestureDetector for handling drag interactions. Only used when no handle is present (entire component is draggable).
state
  • Type: DraggableState
  • Description: Current state of the draggable item.
animatedViewRef
  • Type: ReturnType<typeof useAnimatedRef<Animated.View>>
  • Description: Animated ref for the draggable view. Used internally for measurements.
hasHandle
  • Type: boolean
  • Description: Whether this draggable has a handle component. When true, only the handle can initiate dragging. When false, the entire component is draggable.

DraggingPayload<TData>

Payload object passed to the onDragging callback.

interface DraggingPayload<TData = unknown> {
x: number; // Original X position
y: number; // Original Y position
tx: number; // Current X translation
ty: number; // Current Y translation
itemData: TData; // Data associated with the draggable item
}

Properties

  • x: Original X position of the item
  • y: Original Y position of the item
  • tx: Current X translation from original position
  • ty: Current Y translation from original position
  • itemData: The data associated with the draggable item

DraggableContextValue

Context value for draggable components (used internally).

interface DraggableContextValue {
gesture: any;
state: DraggableState;
}

DraggableProps<TData>

Props for the Draggable component.

interface DraggableProps<TData = unknown> extends UseDraggableOptions<TData> {
style?: StyleProp<ViewStyle>;
children: React.ReactNode;
onStateChange?: (state: DraggableState) => void;
}

Properties

style
  • Type: StyleProp<ViewStyle>
  • Required: No
  • Description: Style to apply to the draggable container.
children
  • Type: React.ReactNode
  • Required: Yes
  • Description: The content to render inside the draggable.
onStateChange
  • Type: (state: DraggableState) => void
  • Required: No
  • Description: Callback fired when the draggable state changes.

DraggableHandleProps

Props for the DraggableHandle component.

interface DraggableHandleProps {
children: React.ReactNode;
style?: StyleProp<ViewStyle>;
}

Properties

children
  • Type: React.ReactNode
  • Required: Yes
  • Description: The content to render inside the handle.
style
  • Type: StyleProp<ViewStyle>
  • Required: No
  • Description: Optional style to apply to the handle.

Usage Examples

Basic Draggable

import { useDraggable, DraggableState } from 'react-native-reanimated-dnd';

interface TaskData {
id: string;
title: string;
priority: 'low' | 'medium' | 'high';
}

function TaskItem({ task }: { task: TaskData }) {
const { animatedViewProps, gesture, state } = useDraggable({
data: task,
onDragStart: (data) => console.log('Started dragging:', data.title),
onDragEnd: (data) => console.log('Finished dragging:', data.title),
onStateChange: (state) => {
if (state === DraggableState.DROPPED) {
showSuccessAnimation();
}
}
});

return (
<GestureDetector gesture={gesture}>
<Animated.View {...animatedViewProps}>
<Text>{task.title}</Text>
<Text>Priority: {task.priority}</Text>
</Animated.View>
</GestureDetector>
);
}

Draggable with Handle

import { Draggable, DraggableHandle } from 'react-native-reanimated-dnd';

function TaskCard({ task }: { task: TaskData }) {
return (
<Draggable data={task}>
<View style={styles.card}>
<DraggableHandle style={styles.handle}>
<Icon name="drag-handle" size={20} />
</DraggableHandle>
<View style={styles.content}>
<Text>{task.title}</Text>
<Text>{task.description}</Text>
</View>
</View>
</Draggable>
);
}

Bounded Draggable

function BoundedDraggable() {
const boundsRef = useRef<View>(null);

return (
<View ref={boundsRef} style={styles.container}>
<Draggable
data={{ id: '1', name: 'Bounded Item' }}
dragBoundsRef={boundsRef}
dragAxis="x"
>
<View style={styles.slider}>
<Text>Drag me horizontally</Text>
</View>
</Draggable>
</View>
);
}

Custom Animation

import { withSpring, withTiming, Easing } from 'react-native-reanimated';

const customBounce: AnimationFunction = (toValue) => {
'worklet';
return withSpring(toValue, {
damping: 10,
stiffness: 100,
mass: 1,
});
};

const customTiming: AnimationFunction = (toValue) => {
'worklet';
return withTiming(toValue, {
duration: 800,
easing: Easing.elastic(2),
});
};

function AnimatedDraggable() {
return (
<Draggable
data={{ id: '1' }}
animationFunction={customBounce}
>
<Text>Bouncy draggable</Text>
</Draggable>
);
}

See Also