Repository: facebook/react
File: packages/react-reconciler/src/ReactFiberHooks.js (JavaScript)

Code before:
  // Order doesn't matter but we insert in the beginning to avoid two fields.
  const update: SwipeTransitionGestureUpdate = {
    gesture: scheduledGesture,
    prev: null,
    next: queue.pending,
  };
  if (queue.pending !== null) {
    queue.pending.prev = update;
  }
  queue.pending = update;
  return function cancelGesture(): void {
    if (update.prev === null) {
      if (queue.pending === update) {
        queue.pending = update.next;
      } else {
        // This was already cancelled. Avoid double decrementing if someone calls this twice by accident.
        // TODO: Should we warn here about double cancelling?
        return;
      }
    } else {
      update.prev.next = update.next;
      if (update.next !== null) {
        update.next.prev = update.prev;
      }
      update.prev = null;
      update.next = null;
    }
    const cancelledGestured = update.gesture;
    // Decrement ref count of the root schedule.
    cancelScheduledGesture(root, cancelledGestured);
  };
}

function mountSwipeTransition<T>(
  previous: T,
  current: T,
  next: T,
): [T, StartGesture] {
  const queue: SwipeTransitionUpdateQueue = {
    pending: null,
    dispatch: (null: any),
    initialDirection: previous === current,
  };
  const startGestureOnHook: StartGesture = (queue.dispatch = (startGesture.bind(
    null,
    currentlyRenderingFiber,
    queue,
  ): any));
  const hook = mountWorkInProgressHook();
  hook.queue = queue;
  return [current, startGestureOnHook];

Review comment (suggestion):
The nested ternaries are tough to reason about here. Might be more readable in if blocks.

Took some stepping through to realize we only look for the `gestureOptions.direction` or `queue.initialDirection` if the currentOffset is the rangeCurrent. I had expected an explicit direction object to override when available. But I guess it makes sense to base off movement because even a one-way gesture needs to be able to reset if its pulled back the other way.

Code after:
  if (__DEV__) {
    if (
      (rangePrevious > rangeCurrent && rangeNext > rangeCurrent) ||
      (rangePrevious < rangeCurrent && rangeNext < rangeCurrent)
    ) {
      console.error(
        'The range of a gesture needs "previous" and "next" to be on either side of ' +
          'the "current" offset. Both cannot be above current and both cannot be below current.',
      );
    }
  }
  const isFlippedDirection = rangePrevious > rangeNext;
  const initialDirection =
    // If a range is specified we can imply initial direction if it's not the current
    // value such as if the gesture starts after it has already moved.
    currentOffset < rangeCurrent
      ? isFlippedDirection
      : currentOffset > rangeCurrent
        ? !isFlippedDirection
        : // Otherwise, look for an explicit option.
          gestureOptions && gestureOptions.direction === 'next'
          ? true
          : gestureOptions && gestureOptions.direction === 'previous'
            ? false
            : // If no option is specified, imply from the values specified.
              queue.initialDirection;
  const scheduledGesture = scheduleGesture(
    root,
    gestureTimeline,
    initialDirection,
    rangePrevious,
    rangeCurrent,
    rangeNext,
  );
  // Add this particular instance to the queue.
  // We add multiple of the same timeline even if they get batched so
  // that if we cancel one but not the other we can keep track of this.
  // Order doesn't matter but we insert in the beginning to avoid two fields.
  const update: SwipeTransitionGestureUpdate = {
    gesture: scheduledGesture,
    prev: null,
    next: queue.pending,
  };
  if (queue.pending !== null) {
    queue.pending.prev = update;
  }
  queue.pending = update;
  return function cancelGesture(): void {
    if (update.prev === null) {
      if (queue.pending === update) {
        queue.pending = update.next;