Skip to content

Commit b1994dd

Browse files
kkafarvzaidman
authored andcommitted
Add invalidation callback for non-recycled component instances on iOS (#53708)
Summary: Since the view recycling is optional on iOS [since 0.74](613a5a7) when a view (with disabled view recycling) is unmounted / destroyed there is no lifecycle callback for a component view to notify it of such event. Currently we (`react-native-screens`) are forced to scan mutation list of every mounting transaction in every of ours container components. Components with view recycling turned on, get `prepareForRecycle` callback on Fabric & on old architecture, there was `invalidate` message sent (`RCTInvalidating` protocol). It would be nice & useful to have something like this for components with view recycling disabled, or enabled but not recycled due to pool being full. In particular in `react-native-screens` we need an information that the component is being destroyed to release retained resources (view controllers & others). I have concern regarding naming of this method, as it could collide / be mistaken with `invalidate` method of `RCTInvalidating` protocol, but naming is hard & I don't see a name that fits better 😄 Open for suggestions! ## 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] [ADDED] - Add invalidation callback for non-recycled component instances Pull Request resolved: #53708 Test Plan: Apply this patch to `RNTMyNativeViewComponentView.mm`: ```objective-c diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm index 2eb7bff..8464da603b 100644 --- a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm @@ -123,6 +123,16 @@ using namespace facebook::react; [_view removeOverlays]; } +- (void)invalidate +{ + NSLog(@"RCTComponentViewProtocol invalidate called"); +} + ++ (BOOL)shouldBeRecycled +{ + return NO; +} + - (void)fireLagacyStyleEvent { RNTMyNativeViewEventEmitter::OnLegacyStyleEvent value = {"Legacy Style Event Fired."}; ``` & render `MyNativeView` in any of the RNTester screens / examples. Unmount the view & observe the log in XCode. https://github.com/user-attachments/assets/be3f67bb-73e0-4af2-9ca1-f2eb9f3347bb (called twice, because there are two components rendered at a time) Reviewed By: javache Differential Revision: D83139361 Pulled By: cipolleschi fbshipit-source-id: 17ef964648ac44b583503b6b00fc5dd457887061
1 parent 6efaeaf commit b1994dd

File tree

4 files changed

+14
-0
lines changed

4 files changed

+14
-0
lines changed

packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ typedef NS_OPTIONS(NSInteger, RNComponentViewUpdateMask) {
111111
*/
112112
- (void)prepareForRecycle;
113113

114+
/*
115+
* Called for unmounted components that won't be moved to a recycle pool.
116+
* Useful for releasing any associated resources.
117+
*/
118+
- (void)invalidate;
119+
114120
/*
115121
* Read the last props used to update the view.
116122
*/

packages/react-native/React/Fabric/Mounting/RCTComponentViewRegistry.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ - (void)_enqueueComponentViewWithComponentHandle:(ComponentHandle)componentHandl
108108
auto &recycledViews = _recyclePool[componentHandle];
109109

110110
if (recycledViews.size() > RCTComponentViewRegistryRecyclePoolMaxSize || !componentViewDescriptor.shouldBeRecycled) {
111+
[componentViewDescriptor.view invalidate];
111112
return;
112113
}
113114

packages/react-native/React/Fabric/Mounting/UIView+ComponentViewProtocol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ NS_ASSUME_NONNULL_BEGIN
3737

3838
- (void)prepareForRecycle;
3939

40+
- (void)invalidate;
41+
4042
- (facebook::react::Props::Shared)props;
4143

4244
- (void)setIsJSResponder:(BOOL)isJSResponder;

packages/react-native/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ - (void)prepareForRecycle
129129
// Default implementation does nothing.
130130
}
131131

132+
- (void)invalidate
133+
{
134+
// Default implementation does nothing.
135+
}
136+
132137
- (facebook::react::Props::Shared)props
133138
{
134139
RCTAssert(NO, @"props access should be implemented by RCTViewComponentView.");

0 commit comments

Comments
 (0)