Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RCTNativeAnimatedNodesManager.mm props is not a node #44072

Open
alexfigliolia opened this issue Apr 13, 2024 · 1 comment
Open

RCTNativeAnimatedNodesManager.mm props is not a node #44072

alexfigliolia opened this issue Apr 13, 2024 · 1 comment
Labels
API: Animated Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍

Comments

@alexfigliolia
Copy link

Description

On iOS using version 0.73.6 I'm encountering several errors coming from RCTNativeAnimatedNodesManager.mm. Particularly when updating or unmounting <Animated.*> components. These errors seem to throw whenever updating or unmounting a component that is potentially in an animated state - be it the component style or display values (for text).

The errors will throw in a small demo I've put together that'll allow you to toggle on and off a shouldComponentUpdate() method and trigger the error. The demo effectively updates the font-size and/or text of an animating node (causing the error) or prevents the error when the shouldComponentUpdate() is active.

It's likely that these errors were never designed to be propagated to the JS runtime, leading me to believe there's something larger at play here. There's a similar open issue for the same module on android that may support the notion that the bug is likely a layer or two deeper.

I've tried several steps to isolate the bug:

  1. Switching JS runtimes between JSCore and Hermes
  2. Blocking re-rendering for specific props that update child nodes vs text values vs styles
  3. Refactoring the components between functional and Component classes

The bug is consistent across each of these steps - so it's likely not a problem with react or variations in JS runtimes.

Steps to reproduce

  1. git clone git@github.com:alexfigliolia/reproducer-react-native.git demo
  2. git clone git@github.com:alexfigliolia/react-native-counter-animation.git
  3. cd into react-native-counter-animation and add the following to the AnimatedNumber.tsx module:
public override shouldComponentUpdate(
    { style }: IAnimatedNumber,
    nextState: State
  ) {
    if (style !== this.props.style) {
      return true;
    }
    return this.state !== nextState;
  }
  1. While in react-native-counter-animation, add the following to the Token.tsx module:
  public override shouldComponentUpdate({ value, style }: Props) {
    if (value !== this.props.value) return true;
    return style !== this.props.style;
  }

The above lines will allow a parent component to update the style of animating nodes while an animation is running. With those lines added, we can package up the code and add it to the demo app.

  1. In react-native-counter-animation run yarn install && yarn build

  2. Add react-native-counter-animation to the demo application's package.json:

{
  "dependencies": {
    "react-native-counter-animation": "file:../react-native-counter-animation"
  }
}
  1. cd into the demo application and run
yarn install && cd ios && bundle install && bundle exec pod install && cd .. && yarn build && yarn start
  1. Open xcode and turn off user script sandboxing for pods and demo build target
  2. Run the app in debug mode by pressing the play button

The app is going to open into a screen with a little graph and counter animation. The corresponding module can be located by searching for <RepairProgress /> and clicking through to the component.

In the component you'll see some code that sends text updates to the counter component on a timer which will throw the error in question as long as renders are not being blocked. The errors will disappear again if the shouldComponentUpdate's from the prior steps are restored to blocking updates.

To show that this bug is not limited just to textual changes, there is a {fontSize !== null && ...} on line 36 of the RepairProgress component that you can remove - allowing the component to calculate it's font-size and update it while the component is mounted. Turning this off will also recreate the error as long as the font size is initialized in some reactive way (theres a useState on line 14 that can be initialized to ~20 instead of null at the top of the component).

I can be available for debugging. Please let me know if you need me :)

React Native Version

0.73.6

Affected Platforms

Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 14.4.1
  CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Memory: 19.16 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 21.6.1
    path: ~/.nvm/versions/node/v21.6.1/bin/node
  Yarn:
    version: 1.22.21
    path: /usr/local/bin/yarn
  npm:
    version: 10.2.4
    path: ~/.nvm/versions/node/v21.6.1/bin/npm
  Watchman:
    version: 2024.04.08.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.4
      - iOS 17.4
      - macOS 14.4
      - tvOS 17.4
      - visionOS 1.1
      - watchOS 10.4
  Android SDK: Not Found
IDEs:
  Android Studio: Not Found
  Xcode:
    version: 15.3/15E204a
    path: /usr/bin/xcodebuild
Languages:
  Java: Not Found
  Ruby:
    version: 3.3.0
    path: /usr/local/opt/ruby/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.73.6
    wanted: 0.73.6
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

Not a props node.

-[RCTNativeAnimatedNodesManager restoreDefaultValues:]
    RCTNativeAnimatedNodesManager.mm:182
__48-[RCTNativeAnimatedModule restoreDefaultValues:]_block_invoke
__56-[RCTNativeAnimatedModule uiManagerWillPerformMounting:]_block_invoke
__44-[RCTUIManager flushUIBlocksWithCompletion:]_block_invoke
__44-[RCTUIManager flushUIBlocksWithCompletion:]_block_invoke_2
__RCTExecuteOnMainQueue_block_invoke
_dispatch_call_block_and_release
_dispatch_client_callout
_dispatch_main_queue_drain
_dispatch_main_queue_callback_4CF
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
__CFRunLoopRun
CFRunLoopRunSpecific
GSEventRunModal
-[UIApplication _run]
UIApplicationMain
main
start_sim
0x0

Reproducer

https://github.com/alexfigliolia/reproducer-react-native

Screenshots and Videos

Simulator.Screen.Recording.-.iPhone.15.Pro.-.2024-04-13.at.09.43.35.mp4
@alexfigliolia
Copy link
Author

It appears there was an old RN version in my yarn cache somehow. I switched over to pnpm, re-installed, and cleaned the build folder. I can't seem to recreate the issue anymore.

@cortinico cortinico added the Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. label Apr 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API: Animated Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍
Projects
None yet
Development

No branches or pull requests

2 participants