Skip to content

[Bug] Animated styles desync after stack navigation back gesture — Reanimated 4.4.1 + Worklets 0.9.1 + Screens 4.25.2 #9614

Description

@centricity-kashifshaikh

Description

After upgrading from Expo SDK 54 (Reanimated 4.1.1) to Expo SDK 56 (Reanimated 4.4.1), useAnimatedStyle styles on a screen render the last-committed native view state instead of the current shared value after navigating away and back using a native stack.

The pattern: Screen A (with animated components) → navigate to Screen B → back to Screen A. On return, the native views show their pre-animation/initial state even though the shared values are correct on the UI thread. A subsequent re-render (any state change) restores the correct appearance.

Two concrete regressions:

  1. Sliding tab indicator driven by translateX via withTiming renders at a stale position
  2. Horizontal bar fillprogress shared value (0→1, withTiming) is at 1 on the UI thread but the native view renders the initial width: 0%

Both worked correctly on Reanimated 4.1.1 (same component code, same navigation pattern). This appears related to — and possibly a regression from — #8363 and #8307 which were marked fixed in 4.1.3.


Affected Patterns

1. Sliding indicator (translateX + width)

A useSharedValue pair (translateX, indicatorWidth) is updated via withTiming inside a useEffect whenever the active tab index changes. A useAnimatedStyle reads these values and applies transform: [{ translateX }] and width.

On return from Screen B:

  • Shared values are at the correct post-animation position (verified)
  • Native Animated.View renders at translateX: 0 / width: 0 (initial state)

2. Sequential fill animation (width: 0% → 100%)

A useSharedValue(0) is driven from 0→1 via withDelay + withTiming inside a useEffect on mount. A useAnimatedStyle maps it to width: \${progress.value * 100}%``.

On return from Screen B:

  • progress.value === 1 on UI thread
  • Native Animated.View renders width: 0%

Steps to Reproduce

  1. Create a screen (Screen A) with the two patterns above inside a react-native-screens native stack (expo-router SDK 56)
  2. Wait for initial animations to complete
  3. Navigate to a child screen (Screen B)
  4. Navigate back (back gesture / hardware back button)
  5. Observed: animated styles render initial/stale state on Screen A
  6. Trigger any re-render → styles instantly snap to correct values

Expected Behaviour

On return to Screen A, useAnimatedStyle reflects the current shared values — same visual state as when the user left.

Actual Behaviour

Native views render their initial/pre-animation state despite shared values being correct. Resolves only on re-render.


Environment

Package Version
react-native-reanimated 4.4.1
react-native-worklets 0.9.1
react-native-screens 4.25.2
expo-router ~56.2.8
react-native 0.85.3
react 19.2.3
Architecture New Architecture (default in Expo SDK 56)
Platform iOS + Android (both affected)

Additional Context

  • Worked: Expo SDK 54 — Reanimated 4.1.1, RN 0.81.5, same component code, same navigation pattern
  • Broken: Expo SDK 56 — Reanimated 4.4.1, RN 0.85.3
  • The desync appears tied to react-native-screens freezing Fabric views when a screen is covered by another screen. Reanimated completes withTiming on the UI thread but the commit never reaches the frozen native view. On unfreeze, the view restores its last-committed style rather than the current shared value.
  • Workaround attempted: re-assigning shared values directly on screen focus (runOnUI(() => { sharedValue.value = target; })()). Partially effective but causes a visible snap/flash which is unacceptable in production.
  • Related issues: Reanimated Components Render Incorrectly After Navigation #8363, Reanimated shared values stopped animating after enabling enableFreeze(true) #8307

Metadata

Metadata

Assignees

No one assigned

    Labels

    Missing infoThe user didn't precise the problem enoughMissing reproThis issue need minimum repro scenario

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions