Skip to content

Commit

Permalink
Merge pull request #600 from dohooo/dev
Browse files Browse the repository at this point in the history
fix: onGestureEnd -> endWithSpring uses outdated data via useSharedValue
  • Loading branch information
dohooo authored May 6, 2024
2 parents d6405aa + d9557b2 commit dd43da8
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/eighty-points-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-native-reanimated-carousel": patch
---

Fixed an issue where endWithSpring used outdated data from useSharedValue after onGestureEnd, causing incorrect carousel behavior on direction reversal.
24 changes: 13 additions & 11 deletions src/components/ScrollViewGesture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,18 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
);

const endWithSpring = React.useCallback(
(onFinished?: () => void) => {
(scrollEndTranslationValue: number,
scrollEndVelocityValue: number,
onFinished?: () => void,
) => {
"worklet";
const origin = translation.value;
const velocity = scrollEndVelocity.value;
const velocity = scrollEndVelocityValue;
// Default to scroll in the direction of the slide (with deceleration)
let finalTranslation: number = withDecay({ velocity, deceleration: 0.999 });

// If the distance of the swipe exceeds the max scroll distance, keep the view at the current position
if (maxScrollDistancePerSwipeIsSet && Math.abs(scrollEndTranslation.value) > maxScrollDistancePerSwipe) {
if (maxScrollDistancePerSwipeIsSet && Math.abs(scrollEndTranslationValue) > maxScrollDistancePerSwipe) {
finalTranslation = origin;
}
else {
Expand All @@ -137,9 +140,9 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
* */
if (pagingEnabled) {
// distance with direction
const offset = -(scrollEndTranslation.value >= 0 ? 1 : -1); // 1 or -1
const offset = -(scrollEndTranslationValue >= 0 ? 1 : -1); // 1 or -1
const computed = offset < 0 ? Math.ceil : Math.floor;
const page = computed(-translation.value / size);
const page = computed(-origin / size);

if (loop) {
const finalPage = page + offset;
Expand Down Expand Up @@ -178,9 +181,7 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
snapEnabled,
translation,
pagingEnabled,
scrollEndVelocity.value,
maxScrollDistancePerSwipe,
scrollEndTranslation.value,
maxScrollDistancePerSwipeIsSet,
],
);
Expand Down Expand Up @@ -335,9 +336,10 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
"worklet";

const { velocityX, velocityY, translationX, translationY } = e;
scrollEndVelocity.value = isHorizontal.value
const scrollEndVelocityValue = isHorizontal.value
? velocityX
: velocityY;
scrollEndVelocity.value = scrollEndVelocityValue; // may update async: see https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue#remarks

let panTranslation = isHorizontal.value
? translationX
Expand All @@ -349,9 +351,9 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
else if (fixedDirection === "positive")
panTranslation = +Math.abs(panTranslation);

scrollEndTranslation.value = panTranslation;
scrollEndTranslation.value = panTranslation; // may update async: see https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue#remarks

const totalTranslation = scrollEndVelocity.value + scrollEndTranslation.value;
const totalTranslation = scrollEndVelocityValue + panTranslation;

/**
* If the maximum scroll distance is set and the translation `exceeds the maximum scroll distance`,
Expand All @@ -374,7 +376,7 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
translation.value = withSpring(withProcessTranslation(nextPage), onScrollEnd);
}
else {
endWithSpring(onScrollEnd);
endWithSpring(panTranslation, scrollEndVelocityValue, onScrollEnd);
}

if (!loop)
Expand Down

0 comments on commit dd43da8

Please sign in to comment.