|
| 1 | +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; |
| 2 | + |
| 3 | +# Native Modules Lifecycle |
| 4 | + |
| 5 | +In React Native, Native Modules are singleton. The Native Module infrastructure lazily creates a Native Modules the first time it is accessed and it keeps it around whenever the app requires it. This is a performance optimization that allows us to avoid the overhead of creating Native Modules eagerly, at app start, and it ensure faster startup times. |
| 6 | + |
| 7 | +In a pure React Native app, the Native Modules are created once and they are never destroyed. However, in more complex apps, there might be use cases where the Native Modules are destroyed and recreated. Imagine, for example, a brownfield app that mixes some native views with some React Native surfaces, as presented in the [Integrating with Existing App guide](/docs/integration-with-existing-apps). In that case it might make sense to destroy a React Native instance when the user navigates away from a React Native surface and recreate it when the user navigates back to that surface. |
| 8 | + |
| 9 | +When this happens, Native Module that are stateless won't cause any issues. However, for stateful Native Modules it might be necessary to properly invalidate the Native Module to ensure that the state is reset and the resources released. |
| 10 | + |
| 11 | +In this guide, you will explore how to initialize and invalidate a Native Module properly. This guide assumes that you are familiar with how to write a Native Modules and you are comfortable writing native code. If you are not familiar with Native Modules, please read the [Native Modules guide](/docs/next/turbo-native-modules-introduction) first. |
| 12 | + |
| 13 | +## Android |
| 14 | + |
| 15 | +When it comes to Android, all the Native Modules already implements a [TurboModule](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.kt) interface that defines two methods: `initialize()` and `invalidate()`. |
| 16 | + |
| 17 | +The `initialize()` method is called by the Native Module infrastructure when the Native Module is created. This is the best place to put all the initialization code that needs access to the ReactApplicationContext, for example. These are some Native Modules from core that implements the `initialize()` method: [BlobModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.java#L155-L157), [NetworkingModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java#L193-L197). |
| 18 | + |
| 19 | +The `invalidate()` method is called by the Native Module infrastructure when the Native Module is destroyed. This is the best place to put all the cleanup code, resetting the Native Module state and release resources that are no longer needed, such as memory and files. These are some Native Modules from core that implements the `invalidate()` method: [DeviceInfoModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/DeviceInfoModule.kt#L72-L76), [NetworkModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java#L200-L212) |
| 20 | + |
| 21 | +## iOS |
| 22 | + |
| 23 | +On iOS, Native Modules conforms to the [`RCTTurboModule`](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h#L196-L200) protocol. However, this protocol does not expose the `initialize` and `invalidate` method that are exposed by the Android's `TurboModule` class. |
| 24 | + |
| 25 | +Instead, on iOS, there are two additional protocols: [`RCTInitializing`](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/Base/RCTInitializing.h) and [`RCTInvalidating`](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/Base/RCTInvalidating.h). These protocols are used to define the `initialize` and `invalidate` methods, respectively. |
| 26 | + |
| 27 | +If your module needs to run some initialization code, then you can conform to the `RCTInitializing` protocol and implement the `initialize` method. To do so, you have to: |
| 28 | + |
| 29 | +1. Moduify the `NativeModule.h` file by adding the following lines: |
| 30 | + |
| 31 | +```diff title="NativeModule.h" |
| 32 | ++ #import <React/RCTInitializing.h> |
| 33 | + |
| 34 | +//... |
| 35 | + |
| 36 | +- @interface NativeModule : NSObject <NativeModuleSpec> |
| 37 | ++ @interface NativeModule : NSObject <NativeModuleSpec, RCTInitializing> |
| 38 | +//... |
| 39 | +@end |
| 40 | +``` |
| 41 | + |
| 42 | +2. Implement the `initialize` method in the `NativeModule.mm` file: |
| 43 | + |
| 44 | +```diff title="NativeModule.mm" |
| 45 | +// ... |
| 46 | + |
| 47 | +@implementation NativeModule |
| 48 | + |
| 49 | ++- (void)initialize { |
| 50 | ++ // add the initialization code here |
| 51 | ++} |
| 52 | + |
| 53 | +@end |
| 54 | +``` |
| 55 | + |
| 56 | +These are some Native Modules from core that implements the `initialize` method: [RCTBlobManager](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/Libraries/Blob/RCTBlobManager.mm#L58-L68), [RCTTiming](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/CoreModules/RCTTiming.mm#L121-L124). |
| 57 | + |
| 58 | +If your module needs to run some cleanup code, then you can conform to the `RCTInvalidating` protocol and implement the `invalidate` method. To do so, you have to: |
| 59 | + |
| 60 | +1. Moduify the `NativeModule.h` file by adding the following lines: |
| 61 | + |
| 62 | +```diff title="NativeModule.h" |
| 63 | ++ #import <React/RCTInvalidating.h> |
| 64 | + |
| 65 | +//... |
| 66 | + |
| 67 | +- @interface NativeModule : NSObject <NativeModuleSpec> |
| 68 | ++ @interface NativeModule : NSObject <NativeModuleSpec, RCTInvalidating> |
| 69 | + |
| 70 | +//... |
| 71 | + |
| 72 | +@end |
| 73 | +``` |
| 74 | + |
| 75 | +2. Implement the `invalidate` method in the `NativeModule.mm` file: |
| 76 | + |
| 77 | +```diff title="NativeModule.mm" |
| 78 | + |
| 79 | +// ... |
| 80 | + |
| 81 | +@implementation NativeModule |
| 82 | + |
| 83 | ++- (void)invalidate { |
| 84 | ++ // add the cleanup code here |
| 85 | ++} |
| 86 | + |
| 87 | +@end |
| 88 | +``` |
| 89 | + |
| 90 | +These are some Native Modules from core that implements the `invalidate` method: [RCTAppearance](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/CoreModules/RCTAppearance.mm#L151-L155), [RCTDeviceInfo](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/CoreModules/RCTDeviceInfo.mm#L127-L133). |
0 commit comments