Skip to content

android: enablePropsUpdateReconciliationAndroid() missing default props in createViewInstance(c, initialProps) #55249

@hannojg

Description

@hannojg

Description

When enabling the enablePropsUpdateReconciliationAndroid feature flag the props will use the getDiffProps() implementation as generated by codegen.

In that implementation when getting props for the first time/mount the logic looks like this:

folly::dynamic ${className}::getDiffProps(
const Props* prevProps) const {
static const auto defaultProps = ${className}();
const ${className}* oldProps = prevProps == nullptr
? &defaultProps
: static_cast<const ${className}*>(prevProps);
if (this == oldProps) {
return folly::dynamic::object();
}
folly::dynamic result = HostPlatformViewProps::getDiffProps(prevProps);
${diffProps}
return result;

Concrete example:

expand Image

The problem with that is that it will only include props that are different from the default props.
Even when manually specifying the prop (with the default value), ie: <MyNativeView isEnabled={true} />. The isEnabled=true won't be received in the mounting layer due to how prop diffing 2.0 operates.
Often this isn't a problem. However, we have a larger app with a lot of view managers using the createViewInstance(tag, context, initialProps, sW?) method.
In there we expect all initial props, including not explicitly set ones, to show up.

I get that when we have prop setter functions we don't want to call them necessarily for initial props as the view should be configured with those defaults in mind.
However, for createViewInstance(tag, context, initialProps, sW?)we often need to know all props to properly create and configure the view.

Because the next problem is that using ReactStylesDiffMap.getBoolean() throws in its isNull check

I am not sure what the ideal solution here is. Some ideas/brainstorming:

  • In Props.cpp we could make sure that is prevProps == nullptr the result will be set to defaultProps, this way the changes will be merged on top and all props will be present
    • Con: this would cause all prop setter functions to be called even for default prop values, not sure if that would break the API expectation
  • My main goal is to not having to duplicate the default props in java. So maybe there could be a getDefaultProps() function bridged via JNI. that could then be used in java to merge the default props on top. Or give the developer the option to use that in createViewInstance
  • If a prop was explicitly set, even if its the default value, make sure it makes it to the mounting layer for initalProps?

Steps to reproduce

  1. Clone/pull from the branch of the reproduction
  2. Go to Components > New Architecture Examples
  3. Crash due to missing prop:

React Native Version

0.84.0-rc.2

Affected Platforms

Runtime - Android

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

System:
  OS: macOS 15.7.3
  CPU: (14) arm64 Apple M4 Pro
  Memory: 189.28 MB / 48.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.14.0
    path: /nix/store/04fc23dsflkxl4s9p6lkigia1hq3vjp2-nodejs-22.14.0/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.yarn/bin/yarn
  npm:
    version: 10.9.2
    path: /nix/store/04fc23dsflkxl4s9p6lkigia1hq3vjp2-nodejs-22.14.0/bin/npm
  Watchman:
    version: 2024.03.11.00
    path: /Users/hannogodecke/Documents/discord/.local/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /Users/hannogodecke/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 25.2
      - iOS 26.2
      - macOS 26.2
      - tvOS 26.2
      - visionOS 26.2
      - watchOS 26.2
  Android SDK:
    API Levels:
      - "31"
      - "34"
      - "35"
      - "36"
    Build Tools:
      - 34.0.0
      - 35.0.0
      - 35.0.1
      - 36.0.0
    System Images:
      - 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-35 | Pre-Release 16 KB Page Size Google APIs ARM 64 v8a
      - android-35 | Google APIs ATD ARM 64
      - android-36 | Google Play ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2025.2 AI-252.25557.131.2521.14344949
  Xcode:
    version: 26.2/17C52
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.15
    path: /Users/hannogodecke/.jenv/shims/javac
  Ruby:
    version: 3.4.4
    path: /Users/hannogodecke/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 19.2.3
    wanted: 19.2.3
  react-native: Not Found
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Stacktrace or Logs

Exception thrown when executing UIFrameGuarded
com.facebook.react.bridge.NoSuchKeyException: horizontal
	at com.facebook.react.bridge.ReadableNativeMap.isNull(ReadableNativeMap.kt:59)
	at com.facebook.react.uimanager.ReactStylesDiffMap.getBoolean(ReactStylesDiffMap.kt:48)
	at com.discord.fastest_list.react.FastestListViewManager.createViewInstance(FastestListViewManager.kt:59)
	at com.discord.fastest_list.react.FastestListViewManager.createViewInstance(FastestListViewManager.kt:32)
	at com.discord.react.utilities.InitialPropsViewGroupManager.createViewInstance(InitialPropsViewGroupManager.kt:20)
	at com.discord.react.utilities.InitialPropsViewGroupManager.createViewInstance(InitialPropsViewGroupManager.kt:9)
	at com.facebook.react.uimanager.ViewManager.createViewInstance(ViewManager.java:216)
	at com.discord.react.utilities.InitialPropsViewGroupManager.createViewInstance(InitialPropsViewGroupManager.kt:30)
	at com.discord.react.utilities.InitialPropsViewGroupManager.createViewInstance(InitialPropsViewGroupManager.kt:9)
	at com.facebook.react.uimanager.ViewManager.createView(ViewManager.java:148)
	at com.facebook.react.fabric.mounting.SurfaceMountingManager.createViewUnsafe(SurfaceMountingManager.java:766)
	at com.facebook.react.fabric.mounting.SurfaceMountingManager.preallocateView(SurfaceMountingManager.java:1194)
	at com.facebook.react.fabric.mounting.mountitems.PreAllocateViewMountItem.execute(PreAllocateViewMountItem.kt:38)
	at com.facebook.react.fabric.mounting.MountItemDispatcher.executeOrEnqueue(MountItemDispatcher.kt:312)
	at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchPreMountItemsImpl(MountItemDispatcher.kt:290)
	at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchPreMountItems(MountItemDispatcher.kt:269)
	at com.facebook.react.fabric.FabricUIManager$DispatchUIFrameCallback.doFrameGuarded(FabricUIManager.java:1518)
	at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.kt:25)
	at com.facebook.react.modules.core.ReactChoreographer.frameCallback$lambda$1(ReactChoreographer.kt:59)
	at com.facebook.react.modules.core.ReactChoreographer.$r8$lambda$nSkFhrr5T7rop_XKwzlLov4NLLw(Unknown Source:0)
	at com.facebook.react.modules.core.ReactChoreographer$$ExternalSyntheticLambda0.doFrame(D8$$SyntheticClass:0)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:2457)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:2468)
	at android.view.Choreographer.doCallbacks(Choreographer.java:1693)
	at android.view.Choreographer.doAnimationLoad(Choreographer.java:1523)
	at android.view.Choreographer.doFrame(Choreographer.java:1438)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:2284)
	at android.os.Handler.handleCallback(Handler.java:1014)
	at android.os.Handler.dispatchMessage(Handler.java:102)
	at android.os.Looper.loopOnce(Looper.java:250)
	at android.os.Looper.loop(Looper.java:340)
	at android.app.ActivityThread.main(ActivityThread.java:9911)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:621)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:957)

MANDATORY Reproducer

#55250

Screenshots and Videos

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs: AttentionIssues where the author has responded to feedback.Needs: ReproThis issue could be improved with a clear list of steps to reproduce the issue.Needs: Version InfoPlatform: AndroidAndroid applications.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions