Skip to content

Commit

Permalink
docs: Fix typos, code examples, and other inconsistencies in Native D…
Browse files Browse the repository at this point in the history
…evelopment section (#4290)
  • Loading branch information
amandeepmittal authored Oct 22, 2024
1 parent 3736a9c commit c878206
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 127 deletions.
2 changes: 1 addition & 1 deletion docs/appendix.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ You may use the following table as a reference for which types are supported and

### Notes:

<b>[1]</b> We strongly recommend using Object literals intead of Objects.
<b>[1]</b> We strongly recommend using Object literals instead of Objects.

:::info
You may also find it useful to refer to the JavaScript specifications for the core modules in React Native. These are located inside the `Libraries/` directory in the React Native repository.
Expand Down
2 changes: 1 addition & 1 deletion docs/the-new-architecture/codegen-cli.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# The Codegen CLI

Calling Gradle or manually calling a script might be hard to remember and it requires a lot of cerimony.
Calling Gradle or manually calling a script might be hard to remember and it requires a lot of ceremony.

To simplify it, we created a CLI tool that can help you running those tasks: the **Codegen** cli. This command runs [react-native-codegen](https://www.npmjs.com/package/react-native-codegen) for your project. The following options are available:

Expand Down
12 changes: 6 additions & 6 deletions docs/the-new-architecture/create-module-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ npx create-react-native-library@latest <Name of Your Library>
4. Continue filling the form until you reach the question _"What type of library do you want to develop?"_
![What type of Library](/docs/assets/what-library.png)
5. For the sake of this guide, select the _Turbo module_ option. Notice that you can create libraries for both New Architecture and Legacy Architecture.
6. Then, you can choose whether you want a library that access the platform (Kotlin & Objective-C) or a sahred C++ library (C++ for Android and iOS).
6. Then, you can choose whether you want a library that access the platform (Kotlin & Objective-C) or a shared C++ library (C++ for Android and iOS).
7. Finally, select the `Test App` as last option. This option creates the library with a separate app already configured within the library folder.

Once the interactive prompt is done, the tool creates a folder whose structure looks like this in Visual Studio Code:
Expand All @@ -45,9 +45,9 @@ Feel free to explore the code that has been created for you. However, the most i
- The `android` folder: this is where the Android code lives
- The `cpp` folder: this is where we the c++ code lives
- The `ios` folder: this is where we the iOS code lives
- The `src` forder: this is where the JS code lives.
- The `src` folder: this is where the JS code lives.

The `package.json` is already configured with all the information that we provided to the `create-react-native-library` tool, including the name and the description of the package. Notice that the `package.json` is also already configured to run codegen.
The `package.json` is already configured with all the information that we provided to the `create-react-native-library` tool, including the name and the description of the package. Notice that the `package.json` is also already configured to run Codegen.

```json
"codegenConfig": {
Expand All @@ -64,7 +64,7 @@ The `package.json` is already configured with all the information that we provid
},
```

Finally the library contains already all the infrastruction to let the library be linked with iOS and Android.
Finally, the library contains already all the infrastructure to let the library be linked with iOS and Android.

### 2. Copy the Code over from Your App

Expand Down Expand Up @@ -105,7 +105,7 @@ To test your library:
4. Build and run Android with `yarn android` from the `example` folder.
5. Build and run iOS with `yarn ios` from the `example` folder.

## Use your library as a Local Module.
## Use your library as a Local Module

There are some scenario where you might want to reuse your library as a local module for your applications, without publishing it to NPM.

Expand Down Expand Up @@ -164,7 +164,7 @@ At this point, you can build and run your app as usual:
- Build and run Android with `yarn android` from the `example` folder.
- Build and run iOS with `yarn ios` from the `example` folder.

## Publish the Library on NPM.
## Publish the Library on NPM

The setup to publish everything on NPM is already in place, thanks to `create-react-native-library`.

Expand Down
10 changes: 5 additions & 5 deletions docs/the-new-architecture/custom-cxx-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default (TurboModuleRegistry.getEnforcing<Spec>(

In this files, we are defining the function that needs to be implemented in C++.

### 3. Implement the Native Code.
### 3. Implement the Native Code

Now, we need to implement the function that we declared in the JS specification.

Expand Down Expand Up @@ -161,7 +161,7 @@ std::string NativeSampleModule::reverseString(jsi::Runtime& rt, std::string inpu
} // namespace facebook::react
```

The implementation imports the `<cmath>` C++ library to perform mathematical operations, then it implements the `cubicRoot` function usinf the `cbrt` primitive from the `<cmath>` module.
The implementation imports the `<cmath>` C++ library to perform mathematical operations, then it implements the `cubicRoot` function using the `cbrt` primitive from the `<cmath>` module.

### 4. Test your code in Your App

Expand Down Expand Up @@ -211,7 +211,7 @@ First, we need to update the `App.tsx` file to use the new method from the Turbo

## Adding a New Structured Custom Type: Address

The approach above can be generalized to any kind of type. For structured types, React Native provides some helper functions that make it easier to bridge them from JS to C++ and viceversa.
The approach above can be generalized to any kind of type. For structured types, React Native provides some helper functions that make it easier to bridge them from JS to C++ and vice versa.

Let's assume that we want to bridge a custom `Address` type with the following properties:

Expand Down Expand Up @@ -288,7 +288,7 @@ It is also possible to have functions that return custom types.

From the `Address` type defined in the specs, Codegen will generate two helper types: `NativeSampleModuleAddress` and `NativeSampleModuleAddressBridging`.

The first type is the definition of the `Address`. The second type contains all the infrastructure to bridge the custom type from JS to C++ and viceversa. The only extra step we need to add is to define the `Bridging` structure that extends the `NativeSampleModuleAddressBridging` type.
The first type is the definition of the `Address`. The second type contains all the infrastructure to bridge the custom type from JS to C++ and vice versa. The only extra step we need to add is to define the `Bridging` structure that extends the `NativeSampleModuleAddressBridging` type.

1. Open the `shared/NativeSampleModule.h` file
2. Add the following code in the file:
Expand Down Expand Up @@ -358,7 +358,7 @@ Once we manually parsed the object, we can implement the logic that we need.
If you want to learn more about `JSI` and how it works, have a look at this [great talk](https://youtu.be/oLmGInjKU2U?feature=shared) from App.JS 2024
:::

### 4. Testing the code in the app.
### 4. Testing the code in the app

To test the code in the app, we have to modify the `App.tsx` file.

Expand Down
155 changes: 60 additions & 95 deletions docs/the-new-architecture/pure-cxx-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ npx @react-native-community/cli@latest init SampleApp --version 0.76.0

Pure C++ Turbo Native Modules are Turbo Native Modules. They needs a specification file (also called spec file) so that Codegen can create the scaffolding code for us. The specification file is also what we use to access the Turbo Native Module in JS.

Specs files need to be written in a typed JS dialect. React Native currently supports Flow or TypeScript
Specs files need to be written in a typed JS dialect. React Native currently supports Flow or TypeScript.

1. Inside the root folder of your app, create a new folder called `specs`.
2. Create a new file called `NativeSampleModule.ts`
2. Create a new file called `NativeSampleModule.ts` with the following code:

:::warning
All Native Turbo Module spec files must have the prefix `Native`, otherwise Codegen will ignore them.
Expand All @@ -34,7 +34,7 @@ All Native Turbo Module spec files must have the prefix `Native`, otherwise Code
<Tabs groupId="tnm-specs" queryString defaultValue={constants.defaultJavaScriptSpecLanguages} values={constants.javaScriptSpecLanguages}>
<TabItem value="flow">

```ts
```ts title="specs/NativeSampleModule.ts"
// @flow
import type {TurboModule} from 'react-native'
import { TurboModuleRegistry } from "react-native";
Expand All @@ -51,7 +51,7 @@ export default (TurboModuleRegistry.getEnforcing<Spec>(
</TabItem>
<TabItem value="typescript">

```ts
```ts title="specs/NativeSampleModule.ts"
import {TurboModule, TurboModuleRegistry} from 'react-native';

export interface Spec extends TurboModule {
Expand All @@ -68,60 +68,23 @@ export default TurboModuleRegistry.getEnforcing<Spec>(

## 2. Configure Codegen

The next step is to configure [Codegen](what-is-codegen.md) in your `package.json`.

1. Open the `package.json` file
2. Modify it as it follows:

```diff
{
"name": "SampleApp",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start",
"test": "jest"
},
"dependencies": {
"react": "18.3.1",
"react-native": "0.76.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@react-native-community/cli": "15.0.0",
"@react-native-community/cli-platform-android": "15.0.0",
"@react-native-community/cli-platform-ios": "15.0.0",
"@react-native/babel-preset": "0.76.0",
"@react-native/eslint-config": "0.76.0",
"@react-native/metro-config": "0.76.0",
"@react-native/typescript-config": "0.76.0",
"@types/react": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.6.3",
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
"react-test-renderer": "18.3.1",
"typescript": "5.0.4"
},
"engines": {
"node": ">=18"
},
+ "codegenConfig": {
+ "name": "AppSpecs",
+ "type": "modules",
+ "jsSrcsDir": "specs",
+ "android": {
+ "javaPackageName": "com.sampleapp.specs"
+ }
+ },
"packageManager": "[email protected]"
}
The next step is to configure [Codegen](what-is-codegen.md) in your `package.json`. Update the file to include:

```json title="package.json"
"start": "react-native start",
"test": "jest"
},
// highlight-add-start
"codegenConfig": {
"name": "AppSpecs",
"type": "modules",
"jsSrcsDir": "specs",
"android": {
"javaPackageName": "com.sampleapp.specs"
}
},
// highlight-add-end
"dependencies": {
```

This configuration tells Codegen to look for specs files in the `specs` folder. It also instruct Codegen to only generate code for `modules` and to namespace the generated code as `AppSpecs`.
Expand All @@ -133,7 +96,7 @@ Writing a C++ Turbo Native Module allow you to share the code between Android an
1. Create a folder named `shared` at the same level of the `android` and `ios` folders.
2. Inside the `shared` folder, create a new file called `NativeSampleModule.h`.

```cpp
```cpp title="shared/NativeSampleModule.h"
#pragma once

#include <AppSpecsJSI.h>
Expand All @@ -156,7 +119,7 @@ Writing a C++ Turbo Native Module allow you to share the code between Android an

3. Inside the `shared` folder, create a new file called `NativeSampleModule.cpp`.

```cpp
```cpp title="shared/NativeSampleModule.cpp"
#include "NativeSampleModule.h"

namespace facebook::react {
Expand All @@ -171,15 +134,12 @@ Writing a C++ Turbo Native Module allow you to share the code between Android an
} // namespace facebook::react
```
Let's have a look at the two files we created.

The `NativeSampleModule.h` file is the header file for a Pure C++ TurboModule. The `include` statements make sure that we include the specs that will be created by Codegen and that contains the interface and the base class we need to implement.

The module lives in the `facebook::react` namespace to have access to all the types that live in that namespace.
Let's have a look at the two files we created:
The class `NativeSampleModule` is the actual Turbo Native Mdoule class and it extends the `NativeSampleModuleCxxSpec` class which contains some glue code and boilerplate code to let this class behave as a Turbo Native Module.

Finally, we have the constructor, that accepts a pointer to the `CallInvoker`, to communicate with JS if needed and the function's prototype we have to implement.
- The `NativeSampleModule.h` file is the header file for a Pure C++ TurboModule. The `include` statements make sure that we include the specs that will be created by Codegen and that contains the interface and the base class we need to implement.
- The module lives in the `facebook::react` namespace to have access to all the types that live in that namespace.
- The class `NativeSampleModule` is the actual Turbo Native Module class and it extends the `NativeSampleModuleCxxSpec` class which contains some glue code and boilerplate code to let this class behave as a Turbo Native Module.
- Finally, we have the constructor, that accepts a pointer to the `CallInvoker`, to communicate with JS if needed and the function's prototype we have to implement.
The `NativeSampleModule.cpp` files is the actual implementation of our Turbo Native Module and implements the constructor and the method that we declared in the specs.
Expand All @@ -193,18 +153,18 @@ This is the only time when we will have to write some platform-specific code.
To make sure that the Android app can effectively build the C++ Turbo Native Module, we need to:
1. Create a `CMakeLists.txt` to access our C++ code
1. Create a `CMakeLists.txt` to access our C++ code.
2. Modify `build.gradle` to point to the newly created `CMakeLists.txt` file.
3. Create an `OnLoad.cpp` file in our Android app to register the new Turbo Native Module.
#### 1. Create the `CMakeLists.txt` file
Android uses CMake to build. CMake needs to access the files we defined in our shared folder, to be able to build them.
1. Create a new folder `SampleApp/android/app/src/main/jni`. The `jni` folder is where the C++ side of Android lives
2. Create a `CMakeLists.txt` file and add this context
1. Create a new folder `SampleApp/android/app/src/main/jni`. The `jni` folder is where the C++ side of Android lives.
2. Create a `CMakeLists.txt` file and add this context:
```shell
```shell title="CMakeLists.txt"
cmake_minimum_required(VERSION 3.13)
# Define the library name here.
Expand All @@ -223,18 +183,18 @@ target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ../../../../../shared)
The CMake file does the following things:

- Defines the `appmodules` library, where all the app C++ code will be included.
- Loads the base React Native's CMake file
- Adds the Module C++ source code that we need to build with the `target_sources` directives. By default React Native will already populate the `appmodules` library with default sources, here we include our custom one. You can see that we need to crawl back from the `jni` folder to the `shared` folder where our C++ TM lives.
- Specify where CMake can find the module header files. Also in this case we need to crawl back from the `jni` folder.
- Loads the base React Native's CMake file.
- Adds the Module C++ source code that we need to build with the `target_sources` directives. By default React Native will already populate the `appmodules` library with default sources, here we include our custom one. You can see that we need to crawl back from the `jni` folder to the `shared` folder where our C++ Turbo Module lives.
- Specifies where CMake can find the module header files. Also in this case we need to crawl back from the `jni` folder.

#### 2. Modify `build.gradle` to include the custom C++ code

Gradle is the tool that orchestrates the Android build. We need to tell it where it can find the `CMake` files to build the Turbo Native Module.

1. Open the `SampleApp/android/app/build.gradle` file
1. Open the `SampleApp/android/app/build.gradle` file.
2. Add the following block into the Gradle file, within the existent `android` block:

```diff
```diff title="android/app/build.gradle"
buildTypes {
debug {
signingConfig signingConfigs.debug
Expand Down Expand Up @@ -270,7 +230,7 @@ curl -O https://raw.githubusercontent.com/facebook/react-native/v0.76.0/packages

2. Then, modify this file as it follows:

```diff
```diff title="android/app/src/main/jni/OnLoad.cpp"
#include <DefaultComponentsRegistry.h>
#include <DefaultTurboModuleManagerDelegate.h>
#include <autolinking.h>
Expand Down Expand Up @@ -325,39 +285,44 @@ To make sure that the iOS app can effectively build the C++ Turbo Native Module,

#### 1. Install Pods and Run Codegen.

The first step we need to run is the usual steps we run every time we have to prepare our iOS application. CocoaPods is the tool we use to setup React Native dependencies and, as part of the process, it will also run Codegen for us.
The first step we need to run is the usual steps we run every time we have to prepare our iOS application. CocoaPods is the tool we use to setup and install React Native dependencies and, as part of the process, it will also run Codegen for us.

1. Navigate to the `ios` folder
2. Run `bundle install` to install the Ruby bundler
3. Run `bundle exec pod install` to install the dependencies and run Codegen
```bash
cd ios
bundle install
bundle exec pod install
```

#### 2. Add the shared folder to the iOS project

This steps adds the `shared` folder to the project to make it visible to xcode.

1. Open the `SampleApp.xcworkspace` file in Xcode.
2. Click on the `SampleApp` project on the left.
3. Select `Add files to "Sample App"...`
4. Select the `shared` folder and click on `Add`
1. Open the CocoPods generated Xcode Workspace.

These images shows you how to add the folder to the project:
```bash
cd ios
open SampleApp.xcworkspace
```

2. Click on the `SampleApp` project on the left and select `Add files to "Sample App"...`.

![Add Files to Sample App...](/docs/assets/AddFilesToXcode1.png)

3. Select the `shared` folder and click on `Add`.

![Add Files to Sample App...](/docs/assets/AddFilesToXcode2.png)

If you did everything right, your project on the left should look like this:

![Xcode Project](/docs/assets/CxxTMGuideXcodeProject.png)

#### 3. Registering the Cxx Turbo Native Module in your app.
#### 3. Registering the Cxx Turbo Native Module in your app

With this last step, we will tell the iOS app where to look for to find the pure C++ Turbo Native Module.

1. In Xcode, open the `AppDelegate.mm` file
2. Modify it as it follows:
In Xcode, open the `AppDelegate.mm` file and modify it as follows:

```diff
```diff title="SampleApp/AppDelegate.mm"
#import <React/RCTBundleURLProvider.h>
+ #import <RCTAppDelegate+Protected.h>
+ #import "NativeSampleModule.h"
Expand Down Expand Up @@ -392,10 +357,10 @@ If you now build your application from Xcode, you should be able to build succes

It's now time to access our C++ Turbo Native Module from JS. To do so, we have to modify the `App.tsx` file to import the Turbo Native Module and to call it in our code.

1. Open the `App.tsx` file
2. Replace the content of the template with the following code
1. Open the `App.tsx` file.
2. Replace the content of the template with the following code:

```ts
```tsx title="App.tsx"
import React from 'react';
import {
Button,
Expand Down Expand Up @@ -460,7 +425,7 @@ export default App;

The interesting lines in this app are:

- `import SampleTurboModule from './specs/NativeSampleModule';`: this lines imports the Turbo Native Module in the app
- `import SampleTurboModule from './specs/NativeSampleModule';`: this line imports the Turbo Native Module in the app,
- `const revString = SampleTurboModule.reverseString(value);` in the `onPress` callback: this is how you can use the Turbo Native Module in your app.

:::warning
Expand Down
Loading

0 comments on commit c878206

Please sign in to comment.