SDK React Native - React Navigation & urql

Mobile integration for DataDome in React Native applications using both React Navigation and urql.
The SDK handles HTTP requests blocked by DataDome in order to display relevant challenge pages, including CAPTCHA.

Compatibility

This SDK is compatible with both CommonJS and ESM setups.
It also provides TypeScript type definitions for strongly-typed projects.

Dependencies

This SDK was developed with the sole intention to be used in React Native projects that are making use of both the React Navigation and urql frameworks.

Apart from the aforementioned dependencies, this package also makes use of:

Installation

Use the npm package manager to install @datadome/mobile-sdk-react-navigation-urql as a dependency of your application.

npm i @datadome/mobile-sdk-react-navigation-urql

iOS installation

After the installation of the npm package is completed, navigate to the ios directory and run a pod installation with CocoaPods.

cd ios/
pod install

❗️

Warning

The CocoaPods installation may occasionally fail, which is a known React Native issue. It is suggested that you clear the ios/build/ directory and run a fresh pod installation, as below:

rm -rf ios/build/
cd ios/
pod install

Usage

App.tsx file changes

The client-side SDK key can be found by logging in to your DataDome dashboard and accessing the Management > Integration tab.

import {
  DataDome,
  navigationRef,
} from "@datadome/mobile-sdk-react-navigation-urql";

// ...

// 1. Create a local DataDome instance
var ddInstance = DataDome.getInstance();

// 2. Set your client-side SDK key
ddInstance.setSdkKey("my-datadome-client-side-sdk-key");

// 3. Set up the map exchange
// Starting from v1.1.0, the DataDome Fetch Wrapper must also be integrated (line 18)
var client = createClient({
  url: "https://datadome.co/graphql",
  fetch: ddInstance.fetchWrapper,
  exchanges: [
    dedupExchange,
    cacheExchange,
    mapExchange(ddInstance.getMapExchange()),
    fetchExchange,
  ],
});

// 4. Provide access to your URQL client
// Warning: the client object will only be used to re-execute the blocked operation,
// such that users will not get stuck whilst using the app.
ddInstance.setUrqlClient(client);

// 5. Include the navigationRef as a prop in your NavigationContainer
function App(): JSX.Element {
  return (
    <NavigationContainer ref={navigationRef}>
      <Provider value={client}>
        <RootNavigation />
      </Provider>
    </NavigationContainer>
  );
}

Root navigation changes

import { DataDomeModal } from "@datadome/mobile-sdk-react-navigation-urql";

// ...

// 1. Register the DataDomeModal as part of your stack
<Stack.Group>
  <Stack.Screen
    name="DataDomeModal"
    component={DataDomeModal}
    options={{ headerShown: false }}
  />
</Stack.Group>;

Advanced use cases

Use an existing navigation ref

In the case that you already have a package that requires setting up its own navigation ref, you can invoke a second DataDome method for our package to use yours.

import { DataDome } from "@datadome/mobile-sdk-react-navigation-urql";

// ...

// 1. Create a local DataDome instance
var ddInstance = DataDome.getInstance();

// 2. Set your client-side SDK key
ddInstance.setSdkKey("my-datadome-client-side-sdk-key");

// 3. Set your navigation ref
ddInstance.setNavRef(merchantNavigationRef);

Use an existing MapExchange

In the case that you have already integrated a MapExchange on your urql client, kindly include DataDome's MapExchange first. This is because exchanges bubble.

var client = createClient({
  url: "https://datadome.co/graphql",
  exchanges: [
    dedupExchange,
    cacheExchange,
    mapExchange(ddInstance.getMapExchange()),
    mapExchange(secondMapExchange()),
    fetchExchange,
  ],
});

Listen to isBlocked flag changes

In the case that you would like to listen to isBlocked flag changes, to trigger state changes or re-renders as required, a static getter named getIsBlocked has been exposed.

The below code snippet makes use of the screenListeners prop to listen to screen state changes and update the local value of the DataDome flag accordingly. Setting up a local flag can then be used as a prop in your components, or alongside useEffect as necessary.

import { DataDome } from "@datadome/mobile-sdk-react-navigation-urql";
import { useEffect, useState } from 'react';

// ...

const RootNavigation = () => {
  const [blockedByDataDome, setBlockedByDataDome] = useState(false);

  useEffect(() => {
    console.log(
      'Blocked by DataDome flag', blockedByDataDome,
    );
  }, [blockedByDataDome]);

  return (
    <Stack.Navigator
      initialRouteName="landingScreen"
      screenListeners={{
        state: e => {
          setBlockedByDataDome(DataDome.getIsBlocked());
        },
      }}>