-
Notifications
You must be signed in to change notification settings - Fork 24.5k
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
[NativeAnimated] Don't restore default values when components unmount #26978
Conversation
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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
If appropriate could you attach before/after videos? |
You can see the bug at the end of this video, the navbar flicker white during the screen back transition: 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: |
There was a problem hiding this 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.
5058bb4
to
e3971df
Compare
@JoshuaGross Rebased and added a JS test |
There was a problem hiding this 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 one of the tests is failing to pass locally:
|
@JoshuaGross Fixed, I forgot to update android tests after changing the signature of restoreDefaultValues (The 2nd parameter was unused). |
@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. |
There was a problem hiding this 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 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. |
This pull request was successfully merged by @janicduplessis in 686ab49. When will my fix make it into a release? | Upcoming Releases |
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