Skip to content

The case for possibility of triggering synchronous layout from UI thread #51815

Open

Description

@kkafar

Description

Follow up to #51809.

This issue report is about lack of support for synchronous layout on UI thread, that is necessary to expose / implement certain platform components, e.g. bottom sheets, without "flicker effect"
(see attached recording).

In current state of Fabric, we, in react-native-screens need to go for ugly & not really working workarounds.

To reproduce the problem it is enough to run the application on iOS (the issue applies also to Android)
& drag the sheet upwards.

Please note that the attached reproduction is minimal - in sense it isn't exactly what we're doing in react-native-screens .
We're not sending an event through event emitter, but rather we update the component's shadow node state - this is also asynchronous and leads to the same effect.

Error mechanism

I'll describe it on iOS example, however the same case can be built for Android.

This is kinda simplified & assumes just one possible order of execution, but should be enough to explain the problem.

Let's consider scenario where we drag the sheet up (see recording to get the context), and the sheet has starting height h1.

  1. User tries to drag the sheet up,
  2. UIKit receives touch & among many things native layout is triggered,
  3. The sheet is resized (height goes up to some h2),
  4. We send asynchronous event (in library code we do an asynchronous shadow node state update),
  5. User continues to drag the sheet up,
  6. Another native sheet resize, sheet has some height h3 now,
  7. React updates state & starts render,
  8. User continues to drag the sheet up,
  9. Another native sheet resize, sheet has some height h4 now,
  10. React render & commit completes & mount is scheduled & let's say executed,
  11. SheetView receives layout computed for the moment sheet had height h2, despite the fact the sheet is already h4.
  12. h4 > h1 - hence the flicker.

I went with sending direct event here, just to simplify the reproduction, but if you need exact setup react-native-screens has, let me know I'll setup custom shadow node for SheetView component.

Motivation

The motivation from #51809 applies.

Additionally, need to be able to do this, e.g. in order to let users implement footer components that pair up with the sheet, or allow for content resizing just as in the reproduction.

Possible solution approach

We need the ability to trigger synchronous state update together with commit, layout & later mount from the UI thread for the high priority UI events, to keep
the interface responsive and in sync with native components, which are crucial for "native app experience".

I know this kinda is behind feature flag
right now & some work is being done around this & together with applying appropriate commit options we would be able to achieve synchronous commit & mount.

Bringing it to your attention to emphasize the need for this feature. At the same time from the perspective of native lib dev want to say that it would be great
to have ability to choose whether state update is synchronous or not (not all updates need to block the UI thread).

Steps to reproduce

  1. Run the app on iOS (the reproduction is set up for that platform)
  2. Drag the sheet up
  3. Observe the flicker

React Native Version

0.79.2

Affected Platforms

Runtime - Android, Runtime - iOS

Areas

Fabric - The New Renderer

Output of npx @react-native-community/cli info

System:
  OS: macOS 15.5
  CPU: (14) arm64 Apple M4 Pro
  Memory: 121.70 MB / 24.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 23.7.0
    path: /opt/homebrew/bin/node
  Yarn:
    version: 1.22.19
    path: /opt/homebrew/bin/yarn
  npm:
    version: 10.9.2
    path: /opt/homebrew/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.16.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.4
      - iOS 18.4
      - macOS 15.4
      - tvOS 18.4
      - visionOS 2.4
      - watchOS 11.4
  Android SDK:
    API Levels:
      - "21"
      - "29"
      - "30"
      - "31"
      - "32"
      - "33"
      - "34"
      - "35"
    Build Tools:
      - 30.0.2
      - 30.0.3
      - 31.0.0
      - 33.0.1
      - 34.0.0
      - 35.0.0
    System Images:
      - android-29 | Google Play ARM 64 v8a
      - android-31 | Google Play ARM 64 v8a
      - android-33 | Google Play ARM 64 v8a
      - android-34 | Google APIs ARM 64 v8a
      - android-34 | Google Play ARM 64 v8a
      - android-35 | Google APIs ARM 64 v8a
      - android-35 | Google Play ARM 64 v8a
      - android-35 | Pre-Release 16 KB Page Size Google Play ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2024.2 AI-242.23726.103.2422.13016713
  Xcode:
    version: 16.3/16E140
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.2
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 18.0.0
    wanted: 18.0.0
  react:
    installed: 19.0.0
    wanted: 19.0.0
  react-native:
    installed: 0.79.2
    wanted: 0.79.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Stacktrace or Logs

N/A

MANDATORY Reproducer

https://github.com/kkafar/layout-issues/tree/%40kkafar/ui-layout-issue <-- please notice the branch!

Screenshots and Videos

Screen.Recording.2025-06-04.at.19.16.06.mov

Activity

  1. kkafar commented on Jun 4, 2025

    @kkafar
    ContributorAuthor

    Hi @cortinico,

    also tagging you here - this is the second issue I've mentioned. Thanks a lot!

  2. cortinico commented on Jun 5, 2025

    @cortinico
    Contributor

    I've passed this over to @sammy-SC

  3. react-native-bot commented on Dec 3, 2025

    @react-native-bot
    Collaborator

    This issue is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.

  4. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    and removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Dec 3, 2025
  5. spasmodiumspam-web commented on Mar 30, 2026

    @spasmodiumspam-web

    It’s honestly difficult to understand why this isn’t a higher priority for the React Native core team. The current situation is creating cascading issues across the ecosystem, with bugs effectively being passed from one library to another. Events are also sent out of order.

    #54636

    Core libraries like react-native-screens are forced into fragile workarounds, which inevitably introduce edge cases and harder-to-diagnose bugs. This then propagates further, with libraries like react-navigation or react-native-keyboard-controller having to compensate for limitations or bugs that really should be addressed at the framework level, particularly around the device insets and keyboard handling on Android. Orientation, for example, is almost fully broken or lacking in react-native-screens due to this issue.

    These are all high-quality libraries maintained by experienced people, but they’re being pushed into solving problems that don’t belong to them. At this point, it feels less like isolated gaps and more like systemic friction in the core. The domino effect.

    Prioritizing these foundational issues would likely deliver significantly more value to the ecosystem than continuing to focus on niche features, especially given how widely these problems surface in real-world apps.

  6. react-native-bot commented on Sep 27, 2026

    @react-native-bot
    Collaborator

    This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

  7. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Sep 27, 2026
  8. removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions