---
title: Starting a DaVinci flow in React Native
description: Start a DaVinci flow in React Native with the useDaVinci hook and share flow state across screens
component: orchsdks
page_id: orchsdks:davinci:usage/react-native/04-starting-a-davinci-flow
canonical_url: https://developer.pingidentity.com/orchsdks/davinci/usage/react-native/04-starting-a-davinci-flow.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, 27 Aug 2026 00:00:00 +0000
keywords: ["DaVinci", "React Native", "Flows", "Starting", "State", "DaVinciProvider"]
section_ids:
  error_handling: Error handling
  sharing: Sharing DaVinci state across screens
---

# Starting a DaVinci flow in React Native

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

* [Prepare](01-configuring-the-server.html)

* [Install](02-installing-the-davinci-module.html)

* [Configure](03-configuring-the-davinci-module.html)

* **Start**

* [Navigate](05-stepping-through-davinci-flows.html)

* [Manage](06-handling-sessions.html)

The recommended way to start and navigate a DaVinci flow in a React Native component is with the `useDaVinci` hook. It returns an object containing the current node and a set of actions.

Use the `start()` action and pass a configured client to start a DaVinci flow:

Starting a flow with useDaVinci

```typescript
const { node, start, loading, error } = useDaVinci(davinciClient);

useEffect(() => {
  start().catch(() => {}); // error surfaced via hook state
}, [start]);
```

|   |                                                                                                                                                                                |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | If you call `useDaVinci()` without an argument, it uses the shared client from a surrounding `DaVinciProvider`.Learn more in [Sharing DaVinci state across screens](#sharing). |

The hook stores the returned node and sets `loading` while `start()` or `next()` is running.

The `error` property contains the most recent hook-level error, or `null` when no hook error has occurred.

The auto-start effect catches the promise rejection because `start()` rejects when the flow cannot start. The hook records the failure in its `error` state, so the catch block can remain empty.

## Error handling

The `start()` action can reject when the module cannot configure or start the DaVinci flow.

The React Native module rejects failed operations with a `DaVinciError`, which extends `PingError` and ultimately extends the standard JavaScript `Error` class.

Use `instanceof DaVinciError` to identify the error and inspect its `code`, `type`, and `message` properties:

Handling an error when starting a DaVinci flow

```typescript
import { DaVinciError, useDaVinci } from '@ping-identity/rn-davinci';
import { Button} from 'react-native';
function LoginScreen() {
  const { start } = useDaVinci(davinciClient);

  async function beginFlow() {
    try {
      await start();
    } catch (err) {
      if (err instanceof DaVinciError) {
        console.error(err.code, err.type, err.message);
      }
    }
  }

  return <Button title="Sign in" onPress={() => beginFlow()} />;
}
```

The stable error codes are:

| Error code                            | Description                                                                                                                                 |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `DAVINCI_ARGUMENT_ERROR`              | The app called an operation with an invalid argument.                                                                                       |
| `DAVINCI_COLLECTOR_APPLY_ERROR`       | A collector value submitted with `next()` could not be applied, for example because its key does not match a collector on the current node. |
| `DAVINCI_CONFIG_ERROR`                | The client configuration is missing or invalid, such as an empty `clientId` or `redirectUri`.                                               |
| `DAVINCI_DISPOSE_ERROR`               | The native flow instance could not be disposed.                                                                                             |
| `DAVINCI_INIT_ERROR`                  | The native DaVinci module could not initialize the flow.                                                                                    |
| `DAVINCI_LOGOUT_ERROR`                | The user could not be signed out.                                                                                                           |
| `DAVINCI_MISSING_INTEGRATION_ERROR`   | A collector requires an integration, such as social sign-on, that the app has not configured.                                               |
| `DAVINCI_NEXT_ERROR`                  | The flow could not advance to the next node.                                                                                                |
| `DAVINCI_POLL_ERROR`                  | A polling operation could not be started.                                                                                                   |
| `DAVINCI_SESSION_ERROR`               | A session operation, such as refreshing or revoking tokens, failed.                                                                         |
| `DAVINCI_START_ERROR`                 | The flow could not be started.                                                                                                              |
| `DAVINCI_STATE_ERROR`                 | An operation was called in an invalid state, such as calling `next()` when the flow has no active node.                                     |
| `DAVINCI_UNKNOWN_ERROR`               | An unexpected error occurred.                                                                                                               |
| `DAVINCI_UNSUPPORTED_COLLECTOR_ERROR` | The app submitted a value for a collector whose type the bridge does not support, so no value can be applied to it.                         |

## Sharing DaVinci state across screens

Each screen that calls `useDaVinci(davinciClient)` gets its own isolated hook state by default.

For example, a `LoginScreen` and an `MfaScreen` would each track their own `node`, `loading`, and `error` values rather than automatically sharing the current flow state.

The DaVinci module provides a `DaVinciProvider` that holds the configured client and shared hook state for descendant components.

Wrapping your navigator, or your entire app, with `DaVinciProvider` means that every screen within it can read and update the same flow state when it calls `useDaVinci()`.

This is useful when a flow moves between screens, such as when a login screen collects credentials and a separate screen collects a multi-factor authentication code.

Using DaVinciProvider to share state across screens

```typescript
import {
  DaVinciProvider,
  useDaVinci,
} from '@ping-identity/rn-davinci';

const davinciClientConfig = {
  modules: {
    oidc: {
      clientId: '6c7eb89a-66e9-ab12-cd34-eeaf795650b2',
      discoveryEndpoint: 'https://auth.pingone.com/3072206d-c6ce-ch15-m0nd-f87e972c7cc3/as/.well-known/openid-configuration',
      redirectUri: 'org.forgerock.demo://oauth2redirect',
    },
  },
};

function App(): React.ReactElement {
  return (
    <DaVinciProvider config={davinciClientConfig}>
      <AuthNavigator />
    </DaVinciProvider>
  );
}

function LoginScreen(): React.ReactElement {
  const { node, start, loading } = useDaVinci();
  return <></>;
}
```

The provider creates one client from the supplied configuration and shares one hook state instance with its descendant components.

|   |                                                                                     |
| - | ----------------------------------------------------------------------------------- |
|   | Calling `useDaVinci()` without either a provider or client raises a `DaVinciError`. |
