---
title: Step 2. Integrating PingOne Protect DaVinci flows in React Native
description: Explains how to develop a client application that integrates with PingOne Protect by initializing data collection, managing behavioral data capture, and returning the collected data to a DaVinci flow.
component: orchsdks
page_id: orchsdks:davinci:use-cases/protect/react-native/02-protect-react-native-app-davinci
canonical_url: https://developer.pingidentity.com/orchsdks/davinci/use-cases/protect/react-native/02-protect-react-native-app-davinci.html
llms_txt: https://developer.pingidentity.com/orchsdks/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: Thu, 8 Oct 2026 00:00:00 +0000
keywords: ["DaVinci", "PingOne Protect", "Client App", "Data Collection", "Risk Evaluation", "React Native"]
section_ids:
  start: Initializing PingOne Protect data collection
  manual: Manual initialization
  on-demand: On-demand initialization
  pause-resume: Pausing and resuming behavioral data capture
  return-data-davinci-flow: Returning data to a DaVinci flow for risk evaluation
  errors: Handling errors
---

# Step 2. Integrating PingOne Protect DaVinci flows in React Native

[icon: circle-check, set=far]PingOne [icon: react, set=fab]React Native

Integrating your application with PingOne Protect enables you to perform risk evaluations during your customer's authentication flow.

The PingOne Protect module runs silently in the background; it requires no user interaction.

## Initializing PingOne Protect data collection

The earlier you can initialize data collection, the more data it can collect to make a risk evaluation.

There are two main methods for initializing data collection in a React Native app:

1. [Manual initialization](#manual)

2. [On-demand initialization](#on-demand)

### Manual initialization

Initialize the PingOne Protect module by calling `startProtect()` with a configuration object:

Initializing the PingOne Protect module at app startup

```typescript
import { startProtect } from '@ping-identity/rn-protect';

await startProtect({
  envId: "3072206d-c6ce-ch15-m0nd-f87e972c7cc3",
  isBehavioralDataCollection: true,
  resumeBehavioralDataOnStart: true,
});
```

The available configuration properties are as follows:

| **Parameter**                  | **Description**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `envId`                        | Required. Your PingOne environment identifier.For example, `3072206d-c6ce-ch15-m0nd-f87e972c7cc3`                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `deviceAttributesToIgnore`     | Optional. A list of device attributes to ignore when collecting device signals.For example, `AUDIO_OUTPUT_DEVICES` or `IS_ACCEPT_COOKIES`.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `isBehavioralDataCollection`   | When `true`, collect behavioral data.Default is `true`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `isConsoleLogEnabled`          | When `true`, output SDK log messages in the developer console.Default is `false`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `isLazyMetadata`               | When `true`, calculate metadata on demand rather than automatically after calling `start`.Default is `false`.                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `customHost`                   | Optional. Specify a custom host for the Protect API, which can be useful in specific deployment scenarios.                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `pauseBehavioralDataOnSuccess` | When `true`, the DaVinci Client automatically pauses behavioral data collection after successful authentication.Default is `false`.&#xA;&#xA;On React Native, this property only takes effect when startProtect() is called before the DaVinci client is created.&#xA;&#xA;In that order, the module injects a lifecycle module into the native client, which pauses behavioral data collection when the flow succeeds. If the client was created first, the property has no effect, and you must call pauseBehavioralData() manually after the flow succeeds. |
| `resumeBehavioralDataOnStart`  | When `true`, the DaVinci Client automatically calls `resumeBehavioralData()` on your behalf, either when the module initializes or when a flow starts.                                                                                                                                                                                                                                                                                                                                                                                                         |

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Call `startProtect()` before creating the DaVinci client.When `startProtect()` runs first, it registers a lifecycle module with the native layer, and that module is injected into the DaVinci client when the client is created. This is what enables the `pauseBehavioralDataOnSuccess` and `resumeBehavioralDataOnStart` properties.If you create the client first, the client does not include the lifecycle module, and those properties have no effect. |

### On-demand initialization

You can choose not to initialize data collection on app startup and instead initialize it when your DaVinci flow reaches a risk evaluation step.

Deferring initialization means your app only collects behavioral data in flows that actually perform PingOne Protect risk evaluations, because behavioral data collection runs continuously once initialized.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | On-demand initialization is incompatible with the `pauseBehavioralDataOnSuccess` and `resumeBehavioralDataOnStart` properties if the DaVinci client is created before `startProtect()` runs, because the lifecycle module is injected into the client only when the client is created after `startProtect()`.If you initialize on demand, pause and resume behavioral data collection manually with the `pauseBehavioralData()` and `resumeBehavioralData()` methods. |

When your DaVinci flow returns a `ContinueNode` containing a `PROTECT` collector, detect it using the `protectCollectorType` constant, initialize the module, and collect the data.

In the following example, `daVinciClient` is a DaVinci client created with `createDaVinciClient()`, as described in [Configuring the DaVinci module in React Native](../../../usage/react-native/03-configuring-the-davinci-module.html), and `node` is the active flow node:

Initializing on demand when a node contains a PROTECT collector

```typescript
import {
  startProtect,
  collectProtect,
  protectCollectorType,
} from '@ping-identity/rn-protect';

// When a ContinueNode arrives:
if (node.collectors.some((c) => c.type === protectCollectorType)) {
  // Initialize the Protect module
  await startProtect({
    envId: '3072206d-c6ce-ch15-m0nd-f87e972c7cc3',
    isBehavioralDataCollection: true,
  });

  // Collect Protect data for the active PROTECT collector
  await collectProtect(daVinciClient);

  // Submit all collectors and get the next node in the flow
  await daVinciClient.next({});
}
```

|   |                                                                                                                                                                                                                                                    |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The native layer does apply one setting from the DaVinci flow during `collectProtect()`: the flow's behavioral data collection setting.When the flow disables behavioral data collection, the native SDK pauses it before gathering the risk data. |

## Pausing and resuming behavioral data capture

Data collection includes collecting behavioral data, such as how the user interacts with the app, to help when performing evaluations.

There are scenarios where you might want to pause the collection of behavioral data:

* To reduce memory and processor utilization. Continuously collecting behavioral data beyond authentication could reduce the performance of your client app.

* When you only want to consider device attribute data when performing PingOne Protect evaluations.

You can pause, and also resume behavioral data collection as required.

The PingOne Protect module provides the `pauseBehavioralData()` and `resumeBehavioralData()` methods for manually pausing and resuming the capture of behavioral data:

Pausing and resuming behavioral data collection

```typescript
import { pauseBehavioralData, resumeBehavioralData } from '@ping-identity/rn-protect';

await pauseBehavioralData(); // Pause data collection.
await resumeBehavioralData(); // Resume data collection.
```

Call `pauseBehavioralData()` after a successful authentication flow, and `resumeBehavioralData()` at the start of a new flow.

If you initialize the PingOne Protect module before you create your DaVinci client, and the DaVinci flows you use complete with a success node, the `pauseBehavioralDataOnSuccess` property pauses behavioral data collection for you. Manual pausing is then only needed if you want to pause at other points.

There are some differences in behavior to be aware of between Android and iOS:

* Android

  * Calling either `pauseBehavioralData()` or `resumeBehavioralData()` before you have initialized PingOne resolves silently on Android.

  * Android returns `PROTECT_INITIALIZE_ERROR` on failures.

* iOS

  * Calling either `pauseBehavioralData()` or `resumeBehavioralData()` before you have initialized PingOne rejects on iOS.

  * iOS returns `PROTECT_COLLECT_ERROR` on failures.

Both methods also accept an optional `logger` property, so you can output log messages from the pause and resume operations:

Passing a logger to the pause and resume methods

```typescript
import { pauseBehavioralData, resumeBehavioralData } from '@ping-identity/rn-protect';
import { logger } from '@ping-identity/rn-logger';

const protectLogger = logger({ level: 'debug' });

await pauseBehavioralData({ logger: protectLogger });
await resumeBehavioralData({ logger: protectLogger });
```

You can pass the same logger instance to the PingOne Protect module itself through the `logger` property in the `startProtect()` configuration.

## Returning data to a DaVinci flow for risk evaluation

To perform risk evaluations, the PingOne server requires the captured data.

When your DaVinci flow reaches a PingOne Protect step, the flow returns a `ContinueNode` containing a `PROTECT` collector.

Call `collectProtect()` with your DaVinci client before you advance the flow. The method runs data collection and sets the resulting payload on the native collector, so that the subsequent `next()` call submits it automatically.

If you use the `useDaVinci` and `useDaVinciForm` hooks to manage form state, as described in [Stepping through DaVinci flows in React Native](../../../usage/react-native/05-stepping-through-davinci-flows.html), collect the Protect data as soon as the node arrives, then submit the form as normal:

Returning Protect data to a DaVinci flow in a React component

```typescript
import { useEffect } from 'react';
import { useDaVinci, useDaVinciForm } from '@ping-identity/rn-davinci';
import { collectProtect, protectCollectorType } from '@ping-identity/rn-protect';

const { node, next } = useDaVinci(daVinciClient);

const form = useDaVinciForm(node, {
  handledCollectorTypes: new Set([protectCollectorType]), (1)
});

// Run Protect data collection as soon as a node with a PROTECT collector arrives
useEffect(() => {
  if (node?.type !== 'ContinueNode') return;

  const hasProtectCollector = node.collectors.some(
    (c) => c.type === protectCollectorType,
  );
  if (!hasProtectCollector) return;

  collectProtect(daVinciClient).catch(console.error); (2)
}, [node]);

async function handleSubmit() {
  // The Protect payload has already been collected by the useEffect above
  if (form.canSubmit) {
    await next(form.input); (3)
  }
}
```

The example above does three things:

1. Passes `protectCollectorType` in `handledCollectorTypes`. 1

   Without this, each `PROTECT` collector raises an `INTEGRATION_REQUIRED` issue and forces `form.canSubmit` to `false`, because the module treats these collectors as requiring client-side integration.

2. Runs `collectProtect()` in a `useEffect` when the node arrives, rather than waiting for submission. 2

   By the time the user submits, the flow has already collected the Protect payload, and the `next(form.input)` call forwards it.

3. Submits the form with `next(form.input)` guarded by `form.canSubmit`. 3

   By doing this the submit reflects the readiness of the remaining form fields. The native layer attaches the Protect payload when the flow advances, so `form.input` needs no Protect value from your app.

If you do not use the hooks, you can call `collectProtect()` directly before you advance the flow:

Returning Protect data without the React hooks

```typescript
import { collectProtect } from '@ping-identity/rn-protect';

async function onSubmitHandler() {
  try {
    // Run Protect data collection for the active PROTECT collector
    await collectProtect(daVinciClient);

    // Submit all collectors and get the next node in the flow
    await daVinciClient.next({});
  } catch (err) {
    // Handle the error, see below
  }
}
```

## Handling errors

All promise rejections from the **Protect** module throw a `ProtectError` instance.

When you collect data in a `useEffect` as shown earlier, handle the rejection there, for example with `.catch()`. Handling the rejection in the effect ensures a collection failure does not go unnoticed if the user still submits the form.

Use `instanceof` to narrow the error type:

Catching and inspecting ProtectError

```typescript
import { ProtectError } from '@ping-identity/rn-protect';

try {
  await collectProtect(daVinciClient);
  await daVinciClient.next({});
} catch (err) {
  if (err instanceof ProtectError) {
    console.log(err.code, err.message);
  }
}
```

The error codes are:

* `PROTECT_INITIALIZE_ERROR`

  The native SDK failed to initialize, pause, or resume data collection.

* `PROTECT_COLLECT_ERROR`

  The native SDK failed to collect risk signals.

* `PROTECT_COLLECTOR_NOT_FOUND`

  The current DaVinci node does not contain an active `PROTECT` collector.
