diff --git a/packages/react-native-reanimated/src/animation/decay/decay.ts b/packages/react-native-reanimated/src/animation/decay/decay.ts index 9e6d5078aa0..5706421c04e 100644 --- a/packages/react-native-reanimated/src/animation/decay/decay.ts +++ b/packages/react-native-reanimated/src/animation/decay/decay.ts @@ -113,6 +113,7 @@ export const withDecay = function ( onFrame: decay, onStart, callback, + forceRunAnimation: true, velocity: config.velocity ?? 0, initialVelocity: 0, current: 0, diff --git a/packages/react-native-reanimated/src/animation/decay/utils.ts b/packages/react-native-reanimated/src/animation/decay/utils.ts index 8d9afc5ff45..131f370c661 100644 --- a/packages/react-native-reanimated/src/animation/decay/utils.ts +++ b/packages/react-native-reanimated/src/animation/decay/utils.ts @@ -13,16 +13,23 @@ const IS_WEB = isWeb(); export const VELOCITY_EPS = IS_WEB ? 1 / 20 : 1; export const SLOPE_FACTOR = 0.1; +/* + * The `forceRunAnimation` prop is necessary to run withDecay animation when + * related sharedValue stays as `0`. It allows to skip animation check and start + * animation immediately + */ + export interface DecayAnimation extends Animation { lastTimestamp: Timestamp; startTimestamp: Timestamp; initialVelocity: number; velocity: number; current: AnimatableValue; + forceRunAnimation: boolean; } export interface InnerDecayAnimation - extends Omit, + extends Omit, AnimationObject { current: number; springActive?: boolean; diff --git a/packages/react-native-reanimated/src/valueSetter.ts b/packages/react-native-reanimated/src/valueSetter.ts index 68f8c65281a..e04b864f2d0 100644 --- a/packages/react-native-reanimated/src/valueSetter.ts +++ b/packages/react-native-reanimated/src/valueSetter.ts @@ -31,6 +31,7 @@ export function valueSetter( // built in animations that are not higher order(withTiming, withSpring) hold target value in .current if ( mutable._value === animation.current && + !animation.forceRunAnimation && !animation.isHigherOrder && !forceUpdate ) {