Skip to content

fix(AnimatedCoordinatesArray): bind decay to the new progress value - #4294

Open
giaBaoJS wants to merge 1 commit into
rnmapbox:mainfrom
giaBaoJS:fix/animated-coordinates-array-decay
Open

fix(AnimatedCoordinatesArray): bind decay to the new progress value#4294
giaBaoJS wants to merge 1 commit into
rnmapbox:mainfrom
giaBaoJS:fix/animated-coordinates-array-decay

Conversation

@giaBaoJS

@giaBaoJS giaBaoJS commented Sep 6, 2026

Copy link
Copy Markdown

Description

AnimatedCoordinatesArray#decay() throws as soon as the returned animation is started, so the method is unusable. timing() and spring() on the same class work.

Reproducer:

import { AnimatedCoordinatesArray } from '@rnmapbox/maps';

const coordinates = new AnimatedCoordinatesArray([
  [1, 1],
  [10, 10],
]);

coordinates
  .decay({
    toValue: [
      [21, 21],
      [30, 30],
    ],
    velocity: 0.001,
    deceleration: 0.997,
    useNativeDriver: false,
  })
  .start();

Before the fix, .start() raises:

TypeError: Cannot read properties of undefined (reading 'stopTracking')

After the fix the animation starts and the coordinates move towards the target.

Root cause

decay() creates a local progressValue, hands it to animate(), but passes this.progressValue to Animated.decay. this.progressValue is only assigned later, inside the onAnimationStart hook that animate() installs, so it is still undefined when the decay animation is built. The sibling methods timing() and spring() pass the local progressValue.

Test

__tests__/utils/animated/AnimatedCoordinatesArray.test.js gains testDecay. It asserts that the value handed to Animated.decay is the Animated.Value the array subscribes to, then starts the animation, advances one frame, and asserts the first coordinate has moved off its start value without passing the target.

With the source change reverted the new test fails on that assertion:

● AnimatedCoordinatesArray › testDecay

  expect(received).toBeInstanceOf(expected)

  Expected constructor: AnimatedValue

  Received value has no prototype
  Received value: undefined

With the change yarn jest goes from 112 to 113 passing tests, 22 suites, no failures. yarn eslint on both changed files is clean, and yarn typecheck reports the same pre-existing errors as on main (all under example/).

The defect is in plain JavaScript with no native side, so it reproduces headlessly under the repo's own jest setup rather than in the /example app. No generated code is affected, so yarn generate was not needed.

Checklist

  • I've read CONTRIBUTING.md

@giaBaoJS
giaBaoJS requested a deployment to CI with Mapbox Tokens September 6, 2026 16:26 — with GitHub Actions Waiting
@giaBaoJS
giaBaoJS requested a deployment to CI with Mapbox Tokens September 6, 2026 16:26 — with GitHub Actions Waiting
@giaBaoJS
giaBaoJS requested a deployment to CI with Mapbox Tokens September 6, 2026 16:26 — with GitHub Actions Waiting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant