React Native Information
  • 13 Oct 2023
  • 3 Minutes to read
  • Contributors
  • Dark
    Light

React Native Information

  • Dark
    Light

Article summary

Information

Information React Native (iOS)

Before following this guide make sure you've setup the Accounts SDK in your React Native App detailed here: https://ignite.ticketmaster.com/docs/clone-react-native-accounts-sdk

This guide will show you how to use Swift Delegates with Native Modules in React Native to let your app know about Authentication State, Tickets State, Analytics and Module changes/information.

In your AccountsSDK.swift class extend TMAuthenticationDelegate

@objc(AccountsSDK)
class AccountsSDK: NSObject, TMAuthenticationDelegate  {


At the start of a method make the class the delegate of TMAuthentication with the following line code 

TMAuthentication.shared.delegate = self


This has to be done before you can receive any state information logs, so it is best you do it during Accounts SDK configuration, or you can create a new native method to be called on React Native on component mount in a useEffect()

Here is an example of setting up the delegate using the configureAccountsSDK() method we wrote in theAccounts SDK  guide

  @objc public func configureAccountsSDK(_ resolve: @escaping (String) -> Void, reject: @escaping (_ code: String, _ message: String, _ error: NSError) -> Void) {

      TMAuthentication.shared.delegate = self

      // build a combination of Settings and Branding
      let tmxServiceSettings = TMAuthentication.TMXSettings(apiKey: "[APIKEY]",
                                                            region: .US)
      
      let branding = TMAuthentication.Branding(displayName: "My Team",
                                               backgroundColor: .red,
                                               theme: .light)
      
      let brandedServiceSettings = TMAuthentication.BrandedServiceSettings(tmxSettings: tmxServiceSettings,
                                                                           branding: branding)

...

 

To get over the Type ‘[CLASS NAME]’ does not conform to protocol 'TMAuthenticationDelegate' error, paste in the below method inside the AccountsSDK class

func onStateChanged(backend: TicketmasterAuthentication.TMAuthentication.BackendService?, state: TicketmasterAuthentication.TMAuthentication.ServiceState, error: (Error)?) {
    print("Backend TicketmasterAuthentication \(state.rawValue)")
    switch state{
    case .serviceConfigurationStarted:
      return
    case .serviceConfigured:
      return
    case .serviceConfigurationCompleted:
      return
    case .loginStarted:
      return
    case .loginPresented:
      return
    case .loggedIn:
      return
    case .loginAborted:
      return
    case .loginFailed:
      return
    case .loginLinkAccountPresented:
      return
    case .loginCompleted:
      return
    case .tokenRefreshed:
      return
    case .logoutStarted:
      return
    case .loggedOut:
      return
    case .logoutCompleted:
      return
    @unknown default:
      return
    }
  }


When there is a change in the Authentication state, the code block of that case will run. You can use Event Emitters to sent this event to React Native

Event emitters

Import the below into your <[Project-Name]>-Bridging-Header.h file

#import <React/RCTEventEmitter.h>


In AccountsSDK.swift instead of NSObject extend RCTEventEmitter

class AccountsSDK: RCTEventEmitter, TMAuthenticationDelegate {




Override a function called supportedEvents by pasting in the following method inside the AccountsSDK class:

  override func supportedEvents() -> [String]! {
    return [];
  }


Replace the return of the loginStarted switch case with: 

self.sendEvent(withName: "loginStarted", body: ["loginStarted:": "loginStarted event sent"])


onStateChanged should look similar to this:

  func onStateChanged(backend: TicketmasterAuthentication.TMAuthentication.BackendService?, state: TicketmasterAuthentication.TMAuthentication.ServiceState, error: (Error)?) {
    print("Backend TicketmasterAuthentication \(state.rawValue)")
    switch state{
...
    case .loginStarted:
      self.sendEvent(withName: "loginStarted", body: ["loginStarted:": "loginStarted event sent"])
...
    @unknown default:
      return
    }
  }



Now add loginStarted to the returned array in the overriding supportedEvents() 

override func supportedEvents() -> [String]! {
    return [“loginStarted”];
  }


Now implement RCTEventEmitter in your Objective-C implementation file by importing the below inside AccountsSDK.m 

#import "React/RCTEventEmitter.h"



Export RCTEventEmitter to expose it to React Native

@interface RCT_EXTERN_MODULE(AccountsSDK, RCTEventEmitter)


The start of your AccountsSDK.m should look similar to the below:

#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"

@interface RCT_EXTERN_MODULE(AccountsSDK, RCTEventEmitter)

- (dispatch_queue_t)methodQueue
{
...


On the React Native side:

In your file where you are calling the Native Accounts SDK methods  import

import {NativeEventEmitter} from 'react-native'


If you’re using React Navigation standard navigation.navigate() navigation won’t trigger a standard useEffects unmount code, so a useCallback can be used with a useFocusEffect to trigger unmount code as shown below 


import React, {useCallback} from 'react'
import {useFocusEffect} from '@react-navigation/native'

const accountsSdkEventEmitter = new NativeEventEmitter(NativeModules.AccountsSDK)

const Home = () => {

…

  
useFocusEffect(
    useCallback(() => {
      accountsSdkEventEmitter.addListener('loginStarted', result => {
        console.log('loginStarted event received', result)
      })
	console.log('useFocusEffect mount called')
      return () => {
        accountsSdkEventEmitter.removeAllListeners('accountsSdkEventEmitter')
        console.log('useFocusEffect unmount called')
      }
    }, []),
  )

return (
…
)

}


For more delegates and the needed functions to implement per delegate see here: https://ignite.ticketmaster.com/docs/information

You can also extend multiple delegates in an NSObject/RCTEventEmitter class

class IgniteO: RCTEventEmitter, TMAuthenticationDelegate, TMTicketsOrderDelegate {


…
}






Android

  • Min SDK: 23
  • Compile SDK: 33
  • Kotlin Version: 1.8.2
  • Gradle Build Tools: 7.4.2
//build.gradle (Module:app)
implementation 'androidx.datastore:datastore-preferences:1.0.0'
implementation 'androidx.datastore:datastore-preferences-rxjava2:1.0.0'
implementation "io.insert-koin:koin-core:3.2.2"
implementation "io.insert-koin:koin-android:3.2.2"

Retail SDK Implementation

//build.gradle (Module:app)
implementation "com.ticketmaster.retail:purchase:1.0.8"
implementation "com.ticketmaster.retail:prepurchase:1.0.5"
implementation "com.ticketmaster.retail:discoveryapi:1.0.2"

Make sure you have the following:

// build.gradle (Module: app)
android {
  .........
  buildFeatures {
    dataBinding = true
  }
}
 <!-- Base application theme within app/src/main/res/values/styles.xml -->
<style name "AppTheme" parent="...">
   ..............
   ..............
   <item name="windowActionBar">false</item>
   <item name="windowNoTitle">true</item> (add if you're using AppCompatActivity)
</style>

Was this article helpful?