-
Notifications
You must be signed in to change notification settings - Fork 24.3k
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
Purge children from view registry when UIManager is invalidated #38617
Purge children from view registry when UIManager is invalidated #38617
Conversation
Base commit: e64756a |
02d13ec
to
e8a2aa7
Compare
Yeah, sure, done. |
Hey, CI fails but it does not look like my change affects it -- rather some kind of build issue. |
Seems reasonable. I'm surprised we don't have another codepath which does this. One other way you could get the right behaviour here is to make sure you stop each root before you tear down React Native, that will cause all views to be unmounted and also will allow useEffect destructors to run. |
Can you rebase? The pod error should've been resolved by ce39931 |
@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
e8a2aa7
to
a4d75dc
Compare
@javache, yeah sure, rebased |
@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Summary: Talking about Paper & iOS here. In standard RN applications when a native component is removed permanently from view hierarchy [it is invalidated (if it implements `RCTInvalidating`)](https://github.com/facebook/react-native/blob/e64756ae5bb5c0607a4d97a134620fafcb132b3b/packages/react-native/React/Modules/RCTUIManager.m#L483-L495). Components that implement `RCTInvalidating` such as [`RNSScreenView`](https://github.com/software-mansion/react-native-screens/blob/9fb3bd00850bcdf29b46daa57e56eabda3ae30ea/ios/RNSScreen.mm#L35) of [`react-native-screens`](https://github.com/software-mansion/react-native-screens) library rely on `RCTInvalidating#invalidate` method being called in adequate moment to release retained resources (in my case the `RNSScreenView` holds a strong reference to it's view controller preventing it from being garbage collected). However in case of brownfield applications (React Native is used only for a particular view & loaded on demand, see: software-mansion/react-native-screens#1754 for discussion & app example) when view controller holding `RCTRootView` is dismissed and whole `React Native` managed view / controller tree gets deallocated, `RCTInvalidating#invalidate` method is not called on the dismissed components, thus in my particular use case, leading to memory leak. Right now I've added call to `RCTUIManager#_purgeChildren:fromRegistry:` (which internally invalidates all components which implement `RCTInvalidating`) in `RCTUIManager#invalidate`. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [IOS][FIXED] - Purge children from view registry on `RCTUIManager` invalidation. Pull Request resolved: #38617 Test Plan: You can run the [demo](https://github.com/mkondakov/RNSScreensMemoryLeak) provided in the [issue](software-mansion/react-native-screens#1754). Following screenshots show that memory leak in brownfield application is resolved. Without the change (`invalidate` method is not being called on native components) ![image](https://github.com/facebook/react-native/assets/50801299/dac331c2-1e7c-4e66-a8c1-b88f7a007d9b) With the change: ![image](https://github.com/facebook/react-native/assets/50801299/7a8afbe9-446c-47a2-a972-d7589b921677) Reviewed By: NickGerleman Differential Revision: D49952215 Pulled By: javache fbshipit-source-id: 6336b86774615acc40279c97e6ae0bb777bda8ad
Summary:
Talking about Paper & iOS here.
In standard RN applications when a native component is removed permanently from view hierarchy it is invalidated (if it implements
RCTInvalidating
). Components that implementRCTInvalidating
such asRNSScreenView
ofreact-native-screens
library rely onRCTInvalidating#invalidate
method being called in adequate moment to release retained resources (in my case theRNSScreenView
holds a strong reference to it's view controller preventing it from being garbage collected).However in case of brownfield applications (React Native is used only for a particular view & loaded on demand, see: software-mansion/react-native-screens#1754 for discussion & app example) when view controller holding
RCTRootView
is dismissed and wholeReact Native
managed view / controller tree gets deallocated,RCTInvalidating#invalidate
method is not called on the dismissed components, thus in my particular use case, leading to memory leak.Right now I've added call to
RCTUIManager#_purgeChildren:fromRegistry:
(which internally invalidates all components which implementRCTInvalidating
) inRCTUIManager#invalidate
.Changelog:
[IOS][FIXED] - Purge children from view registry on
RCTUIManager
invalidation.Test Plan:
You can run the demo provided in the issue.
Following screenshots show that memory leak in brownfield application is resolved.
Without the change (
invalidate
method is not being called on native components)With the change: