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

[NativeAnimated] Don't restore default values when components unmount #26978

Conversation

janicduplessis
Copy link
Contributor

@janicduplessis janicduplessis commented Oct 24, 2019

Summary

There are some cases where restoring default values on component unmount is not desirable. For example in react-native-screens we want to keep the native view displayed after react has unmounted them. Restoring default values causes an issue there because it will change props controlled my native animated back to their default value instead of keeping whatever value they had been animated to.

Restoring default values is only needed for updates anyway, where removing a prop controlled by native animated need to be reset to its default value since react no longer tracks its value.

This splits restoring default values and disconnecting from views in 2 separate native methods, this way we can restore default values only on component update and not on unmount. This takes care of being backwards compatible for OTA JS updates.

Changelog

[General] [Fixed] - NativeAnimated - Don't restore default values when components unmount

Test Plan

  • Tested in an app using react-native-screens to make sure native views that are kept after their underlying component has been unmount don't change. Also tested in RNTester animated example.

  • Tested that new JS works with old native code

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. labels Oct 24, 2019
@janicduplessis
Copy link
Contributor Author

Note: This also requires updating the generated spec to work, I did it manually to test but I'm not sure if codegen is runnable in OSS so I didn't include this change.

restoreDefaultValues: function(nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
// Backwards compat with older native runtimes, can be removed later.
if (NativeAnimatedModule.restoreDefaultValues != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is running against an older runtime, does this check actually work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did test running just the JS without the native changes and it worked fine. On older runtime the function doesn't exist and the disconnectFromView method handles both disconnection and restoring default values.

@JoshuaGross
Copy link
Contributor

If appropriate could you attach before/after videos?

@janicduplessis
Copy link
Contributor Author

janicduplessis commented Oct 27, 2019

You can see the bug at the end of this video, the navbar flicker white during the screen back transition:

https://imgur.com/cPHdnxT

How react-native-screen works for screen animation is when a screen component gets unmounted the native view does not get removed from the native view hierarchy and gets animated. In my app I have a navbar with an opacity value controlled by Animated initially at 0. When the screen gets unmounted the animated native driver would restore the default value for opacity (so 1 in this case) and case the header to show during the transition.

Restoring default values is not needed on component unmount since the view will usually get removed and if it doesn't we want it to keep its current state.

Here's a video after the fix:

https://imgur.com/a/bAZ9O54

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoshuaGross has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@janicduplessis
Copy link
Contributor Author

@JoshuaGross Rebased and added a JS test

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoshuaGross has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@JoshuaGross
Copy link
Contributor

@janicduplessis one of the tests is failing to pass locally:

stderr: /tmp/react-native-github/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.java:984: error: method restoreDefaultValues in class com.facebook.react.animated.NativeAnimatedNodesManager cannot be applied to given types;
    mNativeAnimatedNodesManager.restoreDefaultValues(propsNodeTag, viewTag);
                               ^
  required: int
  found: int,int
  reason: actual and formal argument lists differ in length

@janicduplessis
Copy link
Contributor Author

@JoshuaGross Fixed, I forgot to update android tests after changing the signature of restoreDefaultValues (The 2nd parameter was unused).

@janicduplessis
Copy link
Contributor Author

@JoshuaGross Also do you know what the strategy is to land changes to native modules signature with codegen for OSS PRs? I did not include generated file changes in my PR since AFAIK running codegen in OSS is broken. I did test by editing the codegened files manually.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoshuaGross has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@JoshuaGross
Copy link
Contributor

@janicduplessis Not really sure - longterm we have to fix codegen in OSS. I can't land your diff without running codegen manually, so for now our land-blocking tests will prevent us from merging in anything that breaks trunk.

@react-native-bot
Copy link
Collaborator

This pull request was successfully merged by @janicduplessis in 686ab49.

When will my fix make it into a release? | Upcoming Releases

@react-native-bot react-native-bot added the Merged This PR has been merged. label Nov 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API: Animated Bug CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. Merged This PR has been merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants