> This page is for Applications Protection.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.humansecurity.com/llms.txt.

# Integration with React Native

#### v3.0

The SDK can be integrated into [React Native](https://reactnative.dev/) projects.

## Start the SDK

The automatic interceptor is not supported in React Native, so any request from the JavaScript code has to be handled manually. Here is an example:

```objectivec
PXPolicy policy = new PXPolicy();
policy.setUrlRequestInterceptionType(PXPolicyUrlRequestInterceptionType.NONE);
try {
    PerimeterX.INSTANCE.start(this, "<APP_ID>", this, policy);
}
catch (Exception exception) {
    Log.e("tag","failed to start. error: " + exception.getMessage());
}
```

## Create Native Module

Create a native module which called `PerimeterXModule`, as described [here](https://reactnative.dev/docs/legacy/native-modules-android).

## Pass the SDK's HTTP headers to the JavaScript code

Create a function that pass the HTTP headers from the SDK to the JavaScript code. Here is an example:

```javascript
@ReactMethod
public void getHTTPHeaders(Promise promise) {
    JSONObject json = new JSONObject(PerimeterX.INSTANCE.headersForURLRequest(null));
    promise.resolve(json.toString());
}
```

In your JavaScript code, call this function for every URL request to add those HTTP headers. Here is an example:

```javascript
const headers = await PerimeterXModule.getHTTPHeaders();
const obj = JSON.parse(headers);
const url = 'https://my.request.com'
const response = await fetch(url, {
    method: 'GET',
    headers: obj,
});
```

If you wish to reduce the number of times there is a bridge between the JavaScript and native, you can add a listener that will be called when the SDK's headers were changed. Than, you pass those new headers to the JavaScript side. You may cache those headers for future requests, but you must make sure to update them.

In the `Application`, implement the `PerimeterXDelegate/perimeterxHeadersWereUpdated(headers:forAppId:)` function. You should pass those headers to your native module.

```java
@Override
public void perimeterxHeadersWereUpdated(@NonNull HashMap<String, String> hashMap, @NonNull String s) {
    if (perimeterxModule != null) {
        perimeterxModule.handleUpdatedHeaders(hashMap);
    }
}
```

In the native module, implement the `handleUpdatedHeaders` function. You should send the event (`"pxNewHeaders"`) to the JavaScript side.

```java
public void handleUpdatedHeaders(HashMap<String, String> headers) {
    if (!this.getReactApplicationContext().hasCatalystInstance()) {
        return;
    }
    JSONObject json = new JSONObject(headers);
    this.getReactApplicationContext()
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit("pxNewHeaders", json.toString());
}
```

In your JavaScript code, listen to this event.

1. Import the native module.

   ```javascript
   import {NativeModules, NativeEventEmitter} from 'react-native';
   import type {Message} from 'react-native/Libraries/LogBox/Data/parseLogBoxLog';
   const {PerimeterXModule} = NativeModules;
   ```
2. Create new `NativeEventEmitter`.

   ```javascript
   const pxEventEmitter = new NativeEventEmitter(PerimeterXModule);
   ```
3. Add listener to the event and store the SDK's headers in variable.

   ```javascript
   var pxHeader = null;

   const onAddNewHeaders = headers => {
       const obj = JSON.parse(headers);
       console.log(`[PX] got new px headers from event: ${JSON.stringify(obj)}`);
       pxHeader = obj;
   };

   const subscriptionPxNewHeaders = pxEventEmitter.addListener(
       'PxNewHeaders',
       onAddNewHeaders,
   );
   ```
4. Add those headers to your URL request.

   ```javascript
   const url = 'https://my.request.com'
   const response = await fetch(url, {
       method: 'GET',
       headers: pxHeader,
   });
   ```

> **Headers must be included in all your URL requests**
>
> Those SDK's headers must be included in all your URL requests. Sending requests without them could affect the user experience.

## Handle the block response

You have to provide the SDK with the response. After receiving an error in the response, pass the information to SDK:

```javascript
const result = await PerimeterXModule.handleResponse(
    JSON.stringify(json),
    response.status,
    url,
);
/*
check the result:
  'false' - not handled by the SDK
  'solved' - challenge solved
  'cancelled' - challenge cancelled
*/
if (result === 'solved') {
  // challenge solved. you may retry the request here
} else if (result === 'false') {
  // request finished successfully
} else if (result === 'cancelled') {
  // challenge cancelled
}
```

```java
@ReactMethod
public void handleResponse(String response, Integer code, String url, Promise promise) {
    boolean handled = PerimeterX.INSTANCE.handleResponse(response, null, result -> {
        promise.resolve(result == PerimeterXChallengeResult.SOLVED ? "solved" : "cancelled");
        return null;
    });
    if (!handled) {
        promise.resolve("false");
    }
}
```