• English
  • Deck Hooks

    Factory hooks expose deck state, actions, and interaction values without a provider prop or controller object.

    const ProfileDeck = createSwipeDeck<Profile>();

    useDeckState(id?)

    Returns React-rendered deck state.

    FieldMeaning
    activeIndexCurrent active item index, or -1 before attach.
    countTotal item count in the attached deck.
    isCompletedWhether the deck has consumed all items.
    canSwipeWhether a dismiss action can currently be accepted.
    canUndoWhether the latest valid swipe can currently be restored.
    function Counter() {
      const { activeIndex, count, isCompleted } = ProfileDeck.useDeckState();
      const current = activeIndex >= 0 ? activeIndex + 1 : 0;
    
      return <Text>{isCompleted ? 'Done' : `${current} / ${count}`}</Text>;
    }

    Derive the current item from your own data[activeIndex] when needed. Deck state stays primitive and stable.

    useDeckActions(id?)

    Returns stable action callbacks.

    function Controls() {
      const { canSwipe, canUndo } = ProfileDeck.useDeckState();
      const { swipeLeft, swipeRight, swipeUp, undo } = ProfileDeck.useDeckActions();
    
      return (
        <View>
          <Pressable disabled={!canSwipe} onPress={swipeLeft}>
            <Text>Nope</Text>
          </Pressable>
          <Pressable disabled={!canUndo} onPress={undo}>
            <Text>Undo</Text>
          </Pressable>
          <Pressable disabled={!canSwipe} onPress={swipeRight}>
            <Text>Like</Text>
          </Pressable>
          <Pressable disabled={!canSwipe} onPress={swipeUp}>
            <Text>Up</Text>
          </Pressable>
        </View>
      );
    }

    swipeLeft(), swipeRight(), and swipeUp() return true when accepted and false when the deck is unattached, disabled, animating, unmeasured, completed, or the direction is not allowed. swipeUp() requires allowedDirections to include 'up', but it is not blocked by horizontal drag mode. undo() returns true when canUndo is true, including after the deck is completed.

    useDeckInteraction(id?)

    Returns Reanimated shared values for progress-driven UI.

    function SwipeReactionOverlay() {
      const { intentDirection, progress, signedProgress } = ProfileDeck.useDeckInteraction();
    
      const likeStyle = useAnimatedStyle(() => {
        const progress = Math.max(signedProgress.get(), 0);
    
        return {
          opacity: progress,
          transform: [{ scale: 0.9 + progress * 0.18 }],
        };
      });
    
      const upStyle = useAnimatedStyle(() => {
        const upProgress = intentDirection.get() === 'up' ? progress.get() : 0;
    
        return {
          opacity: upProgress,
          transform: [{ scale: 0.9 + upProgress * 0.18 }],
        };
      });
    
      return (
        <View pointerEvents="none">
          <Animated.Text style={likeStyle}>LIKE</Animated.Text>
          <Animated.Text style={upStyle}>SUPER LIKE</Animated.Text>
        </View>
      );
    }

    Interaction values update on the UI thread and do not rerender React every gesture frame.

    ValueMeaning
    progressDominant enabled-axis progress from 0 to 1.
    signedProgressHorizontal signed progress from -1 to 1; up is 0.
    directionHorizontal live signal: -1, 0, or 1; up is 0.
    intentDirectionPolicy-filtered live semantic intent: 'left', 'right', 'up', or null.
    dismissDirectionAccepted dismiss side: 'left', 'right', 'up', or null.
    translationXActive card horizontal translation.
    translationYActive card vertical translation.
    isDraggingWhether the deck is dragging or dismissing.
    phaseidle, dragging, dismissing, or undoing.

    Use intentDirection for one-at-a-time live reaction overlays. It updates on each drag frame, stays set to an accepted direction while dismissing, and resets with the rest of the interaction values. Use phase for frame-synchronous visual feedback. Use event hooks for committed state changes.