Skip to content

Commit dc233c5

Browse files
authored
feat: Add onDropView() to Hybrid Views (#1266)
* feat: Add `onDropView()` to Hybrid Views * feat: Use `invalidate` on iOS for `onDropView()` * specs * chore: Lint * fix: Whoops Android is optional * chore: simplify * chore: Call `super` last in ondrop * chore: Implement `onDropVIew()` for test
1 parent b0ebb5f commit dc233c5

14 files changed

Lines changed: 96 additions & 9 deletions

File tree

example/ios/Podfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,7 +2217,7 @@ EXTERNAL SOURCES:
22172217

22182218
SPEC CHECKSUMS:
22192219
FBLazyVector: 7c1d69992204c5ec452eeefa4a24b0ff311709c8
2220-
hermes-engine: 16e781d7fca74c8bb3ca59b99527d9633ee9ee36
2220+
hermes-engine: b69aade2dcf59e8c2203c748ca79c7fa4c875053
22212221
NitroModules: fb232c72f7f287543f0c6c214c2a75dce8de8cf3
22222222
NitroTest: 732039c97fdd73f8d95887475ca4a8713696cc06
22232223
NitroTestExternal: eaec60657bfaa38eb3e4eb6e996548221606e428
@@ -2229,7 +2229,7 @@ SPEC CHECKSUMS:
22292229
React: f6f8fc5c01e77349cdfaf49102bcb928ac31d8ed
22302230
React-callinvoker: 3e62a849bda1522c6422309c02f5dc3210bc5359
22312231
React-Core: 0b765bc7c2b83dff178c2b03ed8a0390df26f18c
2232-
React-Core-prebuilt: 88810feb58457484bff17e9e91a15453407d745a
2232+
React-Core-prebuilt: 1ed3b91c7035f715bf741f1b8a2c87e94d126d38
22332233
React-CoreModules: 55b932564ba696301cb683a86385be6a6f137e57
22342234
React-cxxreact: 5bfb95256fde56cc0f9ce425f38cfaa085e71ad2
22352235
React-debug: f9dda2791d3ebe2078bc6102641edab77917efb7
@@ -2292,7 +2292,7 @@ SPEC CHECKSUMS:
22922292
ReactAppDependencyProvider: 23e2bca1661f8781e55fcc05a151fc1df97bc1fb
22932293
ReactCodegen: c049d7e966ed24be56d8e21cb1b8880316975e76
22942294
ReactCommon: 89ccc6cb100ca5a0303b46483037ef8f3e06e2e0
2295-
ReactNativeDependencies: 1a7e3c3ffa57533d8118dd9bc01790ffa9e02a3b
2295+
ReactNativeDependencies: 69de62c8a59d21e7b6af8bdfb62b61e798f65351
22962296
RNScreens: dd61bc3a3e6f6901ad833efa411917d44827cf51
22972297
Yoga: 21f482cbc18b56cdc477cd3a0c5b8c2c83ac27ce
22982298

packages/nitrogen/src/syntax/swift/SwiftHybridObjectBridge.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ public final func maybePrepareForRecycle() {
6969
guard let recyclable = __implementation as? any RecyclableView else { return }
7070
recyclable.prepareForRecycle()
7171
}
72+
`.trim(),
73+
`
74+
public final func onDropView() {
75+
__implementation.onDropView()
76+
}
7277
`.trim()
7378
)
7479
}

packages/nitrogen/src/views/kotlin/KotlinHybridViewManager.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public class ${manager}: SimpleViewManager<View>() {
7575
}
7676
7777
override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
78-
val hybridView = view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
78+
val hybridView = getHybridView(view)
7979
?: throw Error("Couldn't find view $view in local views table!")
8080
8181
// 1. Update each prop individually
@@ -87,9 +87,15 @@ public class ${manager}: SimpleViewManager<View>() {
8787
return super.updateState(view, props, stateWrapper)
8888
}
8989
90+
override fun onDropViewInstance(view: View) {
91+
val hybridView = getHybridView(view)
92+
hybridView?.onDropView()
93+
return super.onDropViewInstance(view)
94+
}
95+
9096
protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
9197
super.prepareToRecycleView(reactContext, view)
92-
val hybridView = view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
98+
val hybridView = getHybridView(view)
9399
?: return null
94100
95101
@Suppress("USELESS_IS_CHECK")
@@ -103,6 +109,10 @@ public class ${manager}: SimpleViewManager<View>() {
103109
return null
104110
}
105111
}
112+
113+
private fun getHybridView(view: View): ${viewImplementation}? {
114+
return view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
115+
}
106116
}
107117
`.trim()
108118

packages/nitrogen/src/views/swift/SwiftHybridViewManager.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ using namespace ${namespace}::views;
150150
swiftPart.maybePrepareForRecycle();
151151
}
152152
153+
- (void)invalidate {
154+
${swiftNamespace}::${HybridTSpecCxx}& swiftPart = _hybridView->getSwiftPart();
155+
swiftPart.onDropView();
156+
[super invalidate];
157+
}
158+
153159
@end
154160
`
155161

packages/react-native-nitro-modules/android/src/main/java/com/margelo/nitro/views/HybridView.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,12 @@ abstract class HybridView : HybridObject() {
2525
* React props are updated in a single batch/transaction.
2626
*/
2727
open fun afterUpdate() { /* noop */ }
28+
29+
/**
30+
* Called when the [HybridView] is about
31+
* to be dropped and unmounted.
32+
* This is a good place to clean up view-related
33+
* resources.
34+
*/
35+
open fun onDropView() { /* noop */ }
2836
}

packages/react-native-nitro-modules/ios/views/HybridView.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,20 @@
2929
* React props are updated in a single batch/transaction.
3030
*/
3131
func afterUpdate()
32+
33+
/**
34+
* Called when the `HybridView` is about
35+
* to be dropped and unmounted.
36+
* This is a good place to clean up view-related
37+
* resources.
38+
*/
39+
func onDropView()
3240
}
3341

3442
extension HybridView {
3543
public func beforeUpdate() { /* noop */ }
3644
public func afterUpdate() { /* noop */ }
45+
public func onDropView() { /* noop */ }
3746
}
3847

3948
extension HybridView {

packages/react-native-nitro-test/android/src/main/java/com/margelo/nitro/test/HybridRecyclableTestView.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.margelo.nitro.test
22

33
import android.graphics.Color
4+
import android.util.Log
45
import android.view.View
56
import androidx.annotation.Keep
67
import com.facebook.proguard.annotations.DoNotStrip
@@ -27,6 +28,10 @@ class HybridRecyclableTestView(
2728
}
2829
}
2930

31+
override fun onDropView() {
32+
Log.i(TAG, "View dropped!")
33+
}
34+
3035
// Recycling conformance
3136
override fun prepareForRecycle() {
3237
view.setBackgroundColor(Color.YELLOW)

packages/react-native-nitro-test/ios/HybridRecyclableTestView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class HybridRecyclableTestView: HybridRecyclableTestViewSpec, RecyclableView {
2222
}
2323
}
2424

25+
func onDropView() {
26+
print("View dropped!")
27+
}
28+
2529
// Recycling conformance
2630
func prepareForRecycle() {
2731
view.backgroundColor = .yellow

packages/react-native-nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/views/HybridRecyclableTestViewManager.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class HybridRecyclableTestViewManager: SimpleViewManager<View>() {
3939
}
4040

4141
override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
42-
val hybridView = view.getTag(associated_hybrid_view_tag) as? HybridRecyclableTestView
42+
val hybridView = getHybridView(view)
4343
?: throw Error("Couldn't find view $view in local views table!")
4444

4545
// 1. Update each prop individually
@@ -51,9 +51,15 @@ public class HybridRecyclableTestViewManager: SimpleViewManager<View>() {
5151
return super.updateState(view, props, stateWrapper)
5252
}
5353

54+
override fun onDropViewInstance(view: View) {
55+
val hybridView = getHybridView(view)
56+
hybridView?.onDropView()
57+
return super.onDropViewInstance(view)
58+
}
59+
5460
protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
5561
super.prepareToRecycleView(reactContext, view)
56-
val hybridView = view.getTag(associated_hybrid_view_tag) as? HybridRecyclableTestView
62+
val hybridView = getHybridView(view)
5763
?: return null
5864

5965
@Suppress("USELESS_IS_CHECK")
@@ -67,4 +73,8 @@ public class HybridRecyclableTestViewManager: SimpleViewManager<View>() {
6773
return null
6874
}
6975
}
76+
77+
private fun getHybridView(view: View): HybridRecyclableTestView? {
78+
return view.getTag(associated_hybrid_view_tag) as? HybridRecyclableTestView
79+
}
7080
}

packages/react-native-nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/views/HybridTestViewManager.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class HybridTestViewManager: SimpleViewManager<View>() {
3939
}
4040

4141
override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
42-
val hybridView = view.getTag(associated_hybrid_view_tag) as? HybridTestView
42+
val hybridView = getHybridView(view)
4343
?: throw Error("Couldn't find view $view in local views table!")
4444

4545
// 1. Update each prop individually
@@ -51,9 +51,15 @@ public class HybridTestViewManager: SimpleViewManager<View>() {
5151
return super.updateState(view, props, stateWrapper)
5252
}
5353

54+
override fun onDropViewInstance(view: View) {
55+
val hybridView = getHybridView(view)
56+
hybridView?.onDropView()
57+
return super.onDropViewInstance(view)
58+
}
59+
5460
protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
5561
super.prepareToRecycleView(reactContext, view)
56-
val hybridView = view.getTag(associated_hybrid_view_tag) as? HybridTestView
62+
val hybridView = getHybridView(view)
5763
?: return null
5864

5965
@Suppress("USELESS_IS_CHECK")
@@ -67,4 +73,8 @@ public class HybridTestViewManager: SimpleViewManager<View>() {
6773
return null
6874
}
6975
}
76+
77+
private fun getHybridView(view: View): HybridTestView? {
78+
return view.getTag(associated_hybrid_view_tag) as? HybridTestView
79+
}
7080
}

0 commit comments

Comments
 (0)