React Native

Integration in a React Native app requires a component that renders a WebView. A WebView that is known to work is React Native WebView.

This guide will walk you through setting up the WebView and making sure your app has direct connection to the Signup module and can receive events and data from it.

1. Add react-native-webview to your dependencies

See the React Native WebView Getting Started Guide for how to add and link it to your project.

2. Create a component with the webview

Pass any custom-data in the onLoadEnd function

import React, {Component} from 'react';
import {View} from 'react-native';
import WebView from 'react-native-webview';

type Props = {};
type State = {};

interface CallbackData {
  action: string;
  regilyData?: string;
  errorKey?: number;
}

interface RegilyError {
  message: string;
  type: string;
  action?: string;
  title?: string;
  key: number;
}

export default class Regily extends Component<Props, State> {
  state = {};
  webView: React.RefObject<WebView>;

  constructor(props: Props | Readonly<Props>) {
    super(props);
    this.webView = React.createRef();
  }

  resolveCallback(errorKey: number) {
    this.webView.current?.injectJavaScript(
      `window.setUpdateSuccess(${errorKey})`,
    );
  }

  rejectCallback(regilyError: RegilyError) {
    this.webView.current?.injectJavaScript(
      `window.setUpdateError('${JSON.stringify(regilyError)}')`,
    );
  }

  render() {
    return (
      // eslint-disable-next-line react-native/no-inline-styles
      <View style={{flex: 1}}>
        <WebView
          ref={this.webView}
          source={{uri: 'https://[partner].regily.com/native.html'}}
          onLoadEnd={() => {
            const customData: string = JSON.stringify({
              enable_otp: false,
            });
            this.webView.current?.injectJavaScript(
              `window.configureAndStart('${customData}')`,
            );
          }}
          // automaticallyAdjustContentInsets={false}
          onMessage={(e: {nativeEvent: {data?: string}}) => {
            /*
             * Handle callbacks (event, update, done)
             *
             * Callbacks (update and done) needs to be resolved or rejected by either calling
             * resolveCallback or rejectCallback with a suitable error
             */
            if (e.nativeEvent.data) {
              const callbackData: CallbackData = JSON.parse(e.nativeEvent.data);
              switch (callbackData.action) {
                case 'update':
                  if (
                    callbackData.regilyData &&
                    callbackData.errorKey !== undefined
                  ) {
                    let data: any = JSON.parse(callbackData.regilyData);
                    if (data && data.credentials && data.credentials.email) {
                      if (data.credentials.email === '[email protected]') {
                        let regilyError: RegilyError = {
                          message: 'Email must be a .com address',
                          type: 'notDotComError',
                          key: callbackData.errorKey,
                          action: 'back',
                          title: 'Some title',
                        };
                        this.rejectCallback(regilyError);
                        return;
                      }
                    }
                  }

                  if (callbackData.errorKey !== undefined) {
                    this.resolveCallback(callbackData.errorKey);
                  }

                  break;
                case 'done':
                  console.log('Done callback: ' + callbackData.regilyData);

                  if (
                    callbackData.regilyData &&
                    callbackData.errorKey !== undefined
                  ) {
                    let data = JSON.parse(callbackData.regilyData);
                    console.log(
                      `Data from flow: ${JSON.stringify(data.mapped)}`,
                    );

                    // TODO send data to backend and call resolveCallback if successful, or else
                    // rejectCallback with a proper error
                    this.resolveCallback(callbackData.errorKey);
                  }
                  break;
                case 'event':
                  console.log('Event callback: ' + callbackData.regilyData);
                  break;
                case 'close-module':
                  console.log('Flow closed. Fly away');
                  break;
                default:
                  console.log('Event: ' + callbackData.action);
                  break;
              }
            }
          }}
          // cacheEnabled={false}
          // cacheMode={'LOAD_NO_CACHE'}
        />
      </View>
    );
  }
}

3. Add any needed validations in the update callback

See Error Handling for more information

4. Finalize the registration

Add a request that creates the user in your backend in the done callback. See Error Handling and Finalize the Registration for more information.

Note that the re-direct needs to be done using your navigation framework (e.g. React Navigation) and not using window.location.href.

If the welcome screen is used, then you have to do the re-direct on the event close-module and you can check if the flow is completed or not by checking the boolean value of callbackData.flowStatus.complete