Skip to main content

The useZoomGesture hook

For advanced use cases, use the useZoomGesture hook directly for full control.

📄 See example/UseZoomGestureExample.tsx for a complete example.

Zoom Component vs useZoomGesture Hook

ApproachSimplicityPerformanceWhen to use
Zoom + onZoomStateChange/onZoomChange✅ Simple⚠️ Via JS bridgeMost use cases
useZoomGesture + useAnimatedReaction⚠️ More complex✅ 120fps, no bridgePerformance-critical apps

Zoom component uses callbacks (onZoomChange, onZoomStateChange) that communicate via the JS bridge. This is simple to use but may have slight delays on rapid updates.

useZoomGesture hook returns SharedValue objects (scale, isZoomedIn) that update directly in the UI thread. Use useAnimatedReaction to respond to changes without JS bridge overhead — ideal for 120fps animations.

Hook API

interface UseZoomGestureProps {
animationFunction?: typeof withTiming // Animation function (default: withTiming)
animationConfig?: object // Configuration for animation function
minScale?: number // Minimum allowed zoom scale (default: 1)
maxScale?: number // Maximum allowed zoom scale (default: 4)
enableGallerySwipe?: boolean // Enable Apple Photos-style gallery swipe (default: false)
parentScrollRef?: RefObject<ScrollableRef> // Parent FlatList/ScrollView ref for seamless scrolling
currentIndex?: number // Current index in parent list
itemWidth?: number // Width of each item in parent list
doubleTapConfig?: DoubleTapConfig // Double tap zoom configuration
}

interface UseZoomGestureReturn {
zoomGesture: ComposedGesture // Gesture handler to attach to GestureDetector
contentContainerAnimatedStyle: object // Animated styles for the content container
onLayout: (event: LayoutChangeEvent) => void // Container layout handler
onLayoutContent: (event: LayoutChangeEvent) => void // Content layout handler
zoomOut: () => void // Programmatically zoom out
isZoomedIn: SharedValue<boolean> // Shared value indicating zoom state
zoomGestureLastTime: SharedValue<number> // Timestamp of last gesture interaction
scale: SharedValue<number> // Current zoom scale (use with useAnimatedReaction)
}

Basic Hook Usage

import { useZoomGesture } from 'react-native-zoom-reanimated'
import { GestureDetector } from 'react-native-gesture-handler'
import Animated from 'react-native-reanimated'

function MyCustomZoomComponent() {
const {
zoomGesture,
contentContainerAnimatedStyle,
onLayout,
onLayoutContent,
zoomOut,
isZoomedIn,
} = useZoomGesture({
doubleTapConfig: { defaultScale: 3, minZoomScale: 1, maxZoomScale: 10 },
})

return (
<GestureDetector gesture={zoomGesture}>
<View onLayout={onLayout}>
<Animated.View style={contentContainerAnimatedStyle} onLayout={onLayoutContent}>
{/* Your zoomable content */}
</Animated.View>
</View>
</GestureDetector>
)
}