NativeScript / NativeScript/runtimes

UIKit host views attach after first React paint

Open
#36 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
25
Forks
4
Avg merge
5d 19h
Merged PRs (30d)
3

Description

Summary

When using @nativescript/react-native UIKit host helpers (defineUIKitView, defineUIKitContainer, and defineUIViewController), the React Native host view can appear on the first paint before the NativeScript-created UIKit subtree/controller is attached. The UIKit content then appears on a later paint.

This makes app startup look two-staged: the React Native shell is visible first, then native nav/tab/accessory/card views pop in. In our app we ended up hiding the root with a double requestAnimationFrame until the native views appear, which feels like the wrong layer for the fix.

Observed behavior

In a React Native/Expo app using @nativescript/react-native@9.0.0-preview.4:

  • UIKit components are defined at module load with defineUIKitView / defineUIKitContainer / defineUIViewController.
  • On initial render, the RN host commits without the native UIKit view/controller handle.
  • The actual UIKit subtree appears on the next render/paint.
  • A native tab/navigation shell therefore needs a timing workaround to avoid visible first-paint flicker.

Expected behavior

If the component is already defined before app render, UIKit-backed host views/controllers should be attachable in the initial host commit, or the package should expose a deterministic precreate/ready mechanism so apps do not need timing hacks.

Likely cause

From reading the package source, defineUIKitHost creates the native UIKit object from a React useEffect. That means the initial render starts with nativeViewHandle, childrenViewHandle, and controllerHandle undefined. After runOnUI() resolves, the package calls setNativeViewHandle, setChildrenViewHandle, and/or setControllerHandle, causing a second React commit where the shared native host finally receives the handles.

So defining the component earlier does not help, because the native object creation/handle publication still happens after the first commit.

Why this matters

Native shell UI such as UITabBarController, UINavigationController, tab bar accessories, and native cards should feel present on the first frame. The current behavior forces app code to either accept a visible two-stage paint or hide the whole shell with timing-based workarounds.

Possible directions

  • Create/publish UIKit handles before the initial React Native host commit when possible.
  • Provide an explicit precreate API for startup-critical native hosts.
  • Provide a deterministic onReady/mounted signal from the package, so apps can hide only until the actual native handle is attached rather than guessing with animation frames.

Happy to provide a small repro if useful.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing defineUIKitHost and its useEffect path, including runOnUI and publication of nativeViewHandle, childrenViewHandle, and controllerHandle. Check how the shared native host receives those handles during the initial commit, then use a small repro with defineUIKitView, defineUIKitContainer, or defineUIViewController to verify that UIKit content is attached on the first paint without timing workarounds.

Written by the indexing model from the issue text.

Assessment

Tech stack
react-native
Domain
frontend, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.