I made a ReactNative App some time ago, and found that many components in ReactNative did not exist, so I still needed to write native modules myself to let JS call them. It was precisely because of many problems encountered in this writing process that I found many deficiencies in the official website documents. So I came up with the idea of writing a practical tutorial, and finally I had this article. This article mainly uses writing a native module as an example to explain some of the knowledge we use in writing native modules. In the whole example, it is equipped with complete practical code to facilitate everyone's understanding and debugging. In addition to these contents, the article also describes how we can publish our own native modules to npm to share them with others. I hope it can be helpful to everyone, and I also hope that everyone will share their own native modules. Example code github address: https://github.com/liuchungui/react-native-BGNativeModuleExample Preparation: Create a ReactNative project We need to create a ReactNative project first. Use the following command to create it.
After creating the project, we use xcode to open the iOS project under TestProject/ios/. Create a static library and manually link it to the project First, we create a folder react-native-BGNativeModuleExample in the node_modules of the ReactNative project we created earlier, and then we create an ios folder under the newly created folder.
Then, since ReactNative components are all static libraries, we need to create a static library if we publish it to npm for others to use. We use Xcode to create a static library named BGNativeModuleExample. After creating it, we copy all the files in the created static library to the node_modules/react- native-BGNativeModuleExample/ios directory. The iOS file directory is as follows:
Finally, we need to manually link this static library into the project. 1. Use Xcode to open the created static library, add a line of Header Search Paths with the value of $(SRCROOT)/../../react-native/React and set it to recursive. 2. Drag the BGNativeModuleExample static library project to the Library in the project. 3. Select TARGETS => TestProject => Build Settings => Link Binary With Libraries and add the static library libBGNativeModuleExample.a At this point, our preparations are complete. We have a purpose for doing this, which is to simulate the process of npm linking, establish the environment, and avoid the problem that others cannot find the static library after publishing it to npm. 1. Writing native module code 1. Create native modules Select the BGNativeModuleExample static library we created, and then import RCTBridgeModule.h in the BGNativeModuleExample.h file to make the BGNativeModuleExample class conform to the RCTBridgeModule protocol.
In the BGNativeModuleExample.m file, we need to implement the RCTBridgeModule protocol. To implement the RCTBridgeModule protocol, our class needs to include the RCT_EXPORT_MODULE() macro. This macro can also add a parameter to specify the name of the module in Javascript. If not specified, the class name will be used by default. Here, we specify the name of the module as BGNativeModuleExample.
After implementing the RCTBridgeModule protocol, we can get the native module we created in js as follows.
It should be noted that the parameter passed by the RCT_EXPORT_MODULE macro cannot be a string in OC. If @"BGNativeModuleExample" is passed, the module name we export to JS is actually @"BGNativeModuleExample", and BGNativeModuleExample cannot be found. Here, we can actually find the native module we created by printing NativeModules. 2. Add methods to native modules We need to explicitly declare the methods to be exported to JS, otherwise ReactNative will not export any methods. The declaration is implemented through the RCT_EXPORT_METHOD() macro:
In JS, we can call this method like this:
3. Parameter Type RCT_EXPORT_METHOD() supports all standard JSON types, including:
In addition, any type supported by the RCTConvert class can be used (see RCTConvert for more information). RCTConvert also provides a series of helper functions that receive a JSON value and convert it to a native Objective-C type or class. To learn more, please click Native Modules. 4. Callback function Warning: This section is currently in an experimental stage, as we don't have much practical experience dealing with callback functions. There is a warning about callback function in the official documentation, but no problem has been found in the use process. In OC, we add a getNativeClass method to call back the class name of the current module to JS.
In JS, we get the class name of the native module in the following way
Native modules should usually only call callbacks once. However, they can save the callback and call it in the future. This is most common when encapsulating iOS APIs that get return values through "delegate functions". 5. Promises Native modules can also use promises to simplify code, and the effect is better when paired with the ES2016 (ES7) standard async/await syntax. If the last two parameters of the bridge native method are RCTPromiseResolveBlock and RCTPromiseRejectBlock, the corresponding JS method will return a Promise object. We use Promises to determine whether the native module will respond to the method. If it responds, it returns YES. If it does not respond, it returns an error message. The code is as follows:
In JS, we have two ways to call, the first is through then....catch:
The second method is called through try...catch. Compared with the first method, the second method will report a warning "Possible Unhandled Promiss Rejection (id:0)".
Note: If we do not need parameters when using Promiss, just remove the name line in OC; if multiple parameters are required, just add an extra line under name. Note that no commas are required between them. 6. Multithreading The module we operate here does not involve UI, so we create a serial queue for it to use, as follows:
Note: Sharing dispatch queues between modules The methodQueue method will be executed once when the module is initialized, and then saved by the React Native bridge mechanism, so you don't need to save the reference to the queue yourself unless you want to use it elsewhere in the module. However, if you want to share the same queue in several modules, you need to save and return the same queue instance yourself; simply returning the queue with the same name is not enough. For more details on thread operations, please refer to: http://reactnative.cn/docs/0.24/native-modules-ios.html#content 7. Export constants Native modules can export constants that are always available on the JavaScript side. This method can be used to pass static data, avoiding a round trip through the bridge. In OC, we implement the constantsToExport method as follows:
In JS, we print this constant
But note that this constant is only exported once at initialization, so even if you change the value returned by constantToExport during runtime, it will not affect the result obtained in the JavaScript environment. 8. Send events to JS Even if it is not called by JS, the local module can send event notifications to JS. The most direct way is to use eventDispatcher. Here, in order to receive events, we start a timer and send an event every second.
In JS, we receive events like this
Note: When writing OC code, you need to add @synthesize bridge = _bridge;, otherwise the error Exception -[BGNativeModuleExample brige]; unrecognized selector sent to instance will be reported when receiving events. The above native code is written, mainly based on code practice to make up for some deficiencies in the official documentation. If you need to know more about native module encapsulation, you can refer to the native module or the official source code. 2. Release and launch After we write the native module according to the above steps, we will publish the native module we wrote to npm. 1. We need to create a github repository Create a repository react-native-BGNativeModuleExample on GitHub, and then link it to the react-native-BGNativeModuleExample directory we created earlier
2. We need to create the entry file of the native module We need to create an index.js in the react-native-BGNativeModuleExample directory, which is the entry point of the entire native module. We just export the native here.
3. Publish to npm Before publishing to npm, we need to create a package.json file, which contains all the information of the module, such as name, version, description, dependencies, author, license, etc. We use the npm init command in the root directory of react-native-BGNativeModuleExample to create package.json. The system will prompt us to enter the required information. If you don't want to enter it, just press Enter to skip it.
After the input is completed, the system will ask us to confirm whether the content of the file is correct. If there is no problem, just enter yes, and the package.json will be created. The package.json file I created here is as follows:
If the native module we write depends on other native modules, we need to add dependencies in package.json. Since we don't have any related dependencies here, we don't need to add them:
After initializing package.json, we can publish it to npm. If you don't have an npm account, you need to register an account. This account will be added to the local npm configuration and used to publish modules.
After success, npm will store the authentication information in ~/.npmrc, and you can view the user currently used by npm with the following command:
After completing the above, we can publish it.
At this point, we have successfully published the module to npmjs.org. Of course, don't forget to publish our code to GitHub.
Sometimes, some files don't need to be published, such as Example files, we can ignore them through .npmignore. For example, the content of my .npmignore file is as follows:
In this case, when we publish it with npm, Example will not be published to npm. 4. Add Example, test whether it is available, and add README We create an Example ReactNative project in the react-native-BGNativeModuleExample directory and install the react-native-nativemodule- example module we released through the rnpm install react-native-nativemodule-example command.
The above prompts that the installation and link are successful, and we can use it in js.
5. We also need to write a README file after the release. The README file is very important. If there is no README file, others will not know what our native component is used for. Therefore, it is necessary to add a README file, which needs to tell others what our native component is used for, how to install it, the API, the user manual, etc. 6. Native module upgrade and new version release When we add new code or fix bugs, we need to release a new version. We only need to modify the version value in the package.json file and then use npm publish to publish it. Summarize This article is mainly divided into two parts. The first part is about writing native modules, and the second part is about publishing what we wrote to npm. refer to How to publish Node modules to the NPM community Native modules |
<<: Who are the top ten highest-paid technology companies in the world that are envied and hated?
>>: Implementing image recognition in Web development based on Google Vision API and Ionic
Security company Lookout recently issued a warnin...
In modern society Mobile phones have become part ...
Android supports three types of processors (CPUs):...
How to promote traffic monetization to improve RO...
With the rapid development of the Internet, mobil...
The report said that among the world's 8 bill...
Author: Hou Jiayi, Deputy Chief Technician, Shanx...
The " random fireworks " in the univers...
0x00 Sequence Ice refers to user state, and fire ...
In actual testing, although there are no major fu...
The space-ground integrated quantum communication...
In the process of SEO optimization , many SEO sta...
With the rapid development of various industries,...
According to the Ministry of Education website, o...
Community operation has been a hot topic and is b...