{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-products/rest/elements/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["partial","code-snippet","json-schema","login-link"]},"type":"markdown"},"seo":{"title":"Enabling Elements in React Native","description":"Embed DailyPay On Demand Pay into your applications with our APIs and SDKs.","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":["openapi"],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"enabling-elements-in-react-native","__idx":0},"children":["Enabling Elements in React Native"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Like other platforms, React requires the same two or three simple steps: Add a web view, handle events/messages, and, in some cases, authenticate the user."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-1-set-up-a-web-view","__idx":1},"children":["Step 1. Set Up a Web View"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Component used: ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.npmjs.com/package/react-native-webview"},"children":["WebView"]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Required Web View Configuration"},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Enable JavaScript"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Enable Web Storage (DOM Storage)"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"web-view-sample","__idx":2},"children":["Web View Sample"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"../code-samples/react/generic-example.tsx","language":"typescript","title":"elements-in-react.tsx","header":{"title":"elements-in-react.tsx","controls":{"copy":{}}},"lang":"typescript","source":"    // Step 1: Setup a \"web view\"\n    <View style={styles.container}>\n      <Text style={styles.text}>DailyPay Elements</Text>\n      <View style={styles.webview}>\n        <WebView\n          cacheEnabled={false} // Disable caching for development\n          ref={dpElementWebView}\n          source={{ uri: dpElementUrl.toString() }}\n          style={{ flex: 1 }}\n          onMessage={handleMessageFromElement}\n          domStorageEnabled={true}  // [!code highlight]\n          javaScriptEnabled={true}  // [!code highlight]\n        />\n      </View>\n      <View style={{ height: 100, margin: 10, flex: 1 }}>\n        <Text style={styles.text}>Log:</Text>\n        <ScrollView contentContainerStyle={{ flexGrow: 1 }}>\n          <Text style={styles.text}>{logMessages}</Text>\n        </ScrollView>\n      </View>\n      <View>\n        <Text style={styles.text}>Type:</Text>\n        <TextInput\n          style={styles.input}\n          value={inputMessageType}\n          onChangeText={setInputMessageType}\n        />\n        <Text style={styles.text}>Payload (JSON):</Text>\n        <TextInput\n          style={styles.input}\n          value={inputMessagePayload}\n          onChangeText={setInputMessagePayload}\n        />\n        <Button\n          title=\"Send Message\"\n          onPress={() =>\n            sendMessageToElement(inputMessageType, JSON.parse(inputMessagePayload))\n          }\n        />\n      </View>\n    </View>\n    ","wrapContents":true},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-2-set-up-eventmessage-handling","__idx":3},"children":["Step 2. Set Up Event/Message Handling"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"sending-events","__idx":4},"children":["Sending Events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Method used: ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md#postmessagestr"},"children":["postMessage"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Please ",{"$$mdtype":"Tag","name":"MarkdocLoginLink","attributes":{},"children":[]}," to view this content."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"send-message-sample-code","__idx":5},"children":["Send Message Sample Code"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"../code-samples/react/generic-example.tsx","language":"typescript","title":"elements-in-react.tsx","header":{"title":"elements-in-react.tsx","controls":{"copy":{}}},"lang":"typescript","source":"  // Step 2: Setup Communications: Event/Message Handling\n  // Step 2a: Send Event to Elements\n  const sendMessageToElement = (type: string, payload: object) => {\n    const message = { type: type, payload: payload };\n    if (dpElementWebView.current) {\n      dpElementWebView.current.postMessage(JSON.stringify(message), dpElementOrigin);\n      setLogMessages(\n        (prevMessages) =>\n          \"Sent: \" + JSON.stringify(message) + \"\\n\" + prevMessages,\n      );\n    }\n  };\n\n  ","wrapContents":true},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"listening-for-events","__idx":6},"children":["Listening for Events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Property used: ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md#onmessage"},"children":["onMessage"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Please ",{"$$mdtype":"Tag","name":"MarkdocLoginLink","attributes":{},"children":[]}," to view this content."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"receive-message-sample-code","__idx":7},"children":["Receive Message Sample Code"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"../code-samples/react/generic-example.tsx","language":"typescript","title":"elements-in-react.tsx","header":{"title":"elements-in-react.tsx","controls":{"copy":{}}},"lang":"typescript","source":"  // Step 2b: Listen for events from Elements\n  const handleMessageFromElement = (event: WebViewMessageEvent) => {\n    const receivedEvent = event.nativeEvent;\n    // Log the raw event for debugging and illustration\n    console.log(\"Raw event received:\", receivedEvent);\n    // It is crucial to verify the origin of the message for security reasons.\n    if (receivedEvent.url.startsWith(dpElementOrigin) === false) {\n      console.warn(\"Received message from unknown origin:\", receivedEvent.url);\n      return;\n    }\n    // Parse the received data - it should be a JSON formatted string\n    let receivedMessage;\n    try {\n      receivedMessage = JSON.parse(receivedEvent.data);\n    } catch (e) {\n      console.error(\"Invalid JSON in payload input:\", e);\n      return;\n    }\n    console.log(\"Message from WebView:\", receivedMessage);\n    if (receivedMessage && receivedMessage.type) {\n      setLogMessages(\n        (prevMessages) =>\n          \"Received: \" + JSON.stringify(receivedMessage) + \"\\n\" + prevMessages,\n      );\n      switch (receivedMessage.type) {\n        case \"DAILYPAY_CARD_TOKENIZE_RESPONSE\":\n          console.log(\"DAILYPAY_CARD_TOKENIZE_RESPONSE received: \", receivedMessage.success);\n          console.log(\"DAILYPAY_CARD_TOKENIZE_RESPONSE received: \", receivedMessage.response);\n          // Call API create account function\n          break;\n        case \"EXT_LOG\":\n          // Log if needed\n          console.log(\"EXT_LOG received: \", receivedMessage.payload);\n          break;\n        case \"EXT_NEED_AUTH\":\n          console.log(\"EXT_NEED_AUTH received: \", receivedMessage.payload);\n          handleExtNeedAuth();\n          break;\n        default:\n          console.log(\"Unhandled event type: \", receivedMessage.type);\n      }\n    }\n  };\n  ","wrapContents":true},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-3-set-up-user-authentication-optional","__idx":8},"children":["Step 3. Set Up User Authentication (Optional)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Authentication Message Sample Code:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"../code-samples/react/generic-example.tsx","language":"typescript","title":"elements-in-react.tsx","header":{"title":"elements-in-react.tsx","controls":{"copy":{}}},"lang":"typescript","source":"  // Step 3: Setup Authentication\n  var dpAuthTokens: AuthorizeResult | RefreshResult | null = null;\n  const dpAuthConfig: AuthConfiguration = {\n    issuer: 'https://auth.uat.dailypay.com',\n    clientId: 'REPLACE_WITH_YOUR_OAUTH_CLIENT_ID',\n    redirectUrl: 'REPLACE_WITH_YOUR_APP_REDIRECT_URI',\n    scopes: ['user:read'],\n    serviceConfiguration: {\n      authorizationEndpoint: 'https://auth.uat.dailypay.com/oauth2/auth',\n      tokenEndpoint: 'https://auth.uat.dailypay.com/oauth2/token',\n    },\n  };\n\n  const dpAuthenticateUser = async () => {\n    try {\n      const dpAuthTokens: AuthorizeResult = await authorize(dpAuthConfig);\n      console.log('Authorization successful:', dpAuthTokens);\n      // Save token in secure storage\n      await SecureStore.setItemAsync('dpAuthTokens', JSON.stringify(dpAuthTokens));\n      // Send token to WebView\n      sendMessageToElement('GIVE_TOKEN', { token: dpAuthTokens.accessToken });\n    } catch (error) {\n      console.error('Authorization failed:', error);\n      dpAuthTokens = null;\n      // Handle authentication errors\n    }      \n  };\n  \n  const handleExtNeedAuth = async () => {\n    // Check secure storage for existing tokens\n    let dpAuthTokensString = await SecureStore.getItemAsync('dpAuthTokens');\n    if (dpAuthTokensString) {\n      dpAuthTokens = JSON.parse(dpAuthTokensString);\n      console.log('Found existing tokens:', dpAuthTokens);\n      // Check if token is expired\n      if (dpAuthTokens && dpAuthTokens.refreshToken && Date.parse(dpAuthTokens.accessTokenExpirationDate) < Date.now()) {\n        try{\n          dpAuthTokens = await refresh(dpAuthConfig, {\n            refreshToken: dpAuthTokens.refreshToken,\n          });\n          console.log('Token refresh successful:', dpAuthTokens);\n          await SecureStore.setItemAsync('dpAuthTokens', JSON.stringify(dpAuthTokens));\n        } catch (error) {\n          console.warn('Token refresh failed:', error);\n          dpAuthTokens = null;\n          dpAuthenticateUser();\n        };\n      };\n    } else {\n      console.log('No tokens found, initiating login.');\n      dpAuthenticateUser();\n    };\n    if (dpAuthTokens) {\n      console.log(dpAuthTokens)\n      sendMessageToElement('GIVE_TOKEN', { token: dpAuthTokens.accessToken });\n    } else {\n      console.warn('No valid tokens available, user needs to log in.');\n    };\n  };\n  ","wrapContents":true},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"full-sample-code","__idx":9},"children":["Full Sample Code"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"../code-samples/react/generic-example.tsx","language":"ts","title":"elements-in-react.tsx","header":{"title":"elements-in-react.tsx","controls":{"copy":{}}},"lang":"ts","source":"import * as SecureStore from 'expo-secure-store';\nimport React, { useRef, useState } from \"react\";\nimport {\n  Button,\n  ScrollView,\n  StyleSheet,\n  Text,\n  TextInput,\n  View,\n} from \"react-native\";\nimport { AuthConfiguration, authorize, AuthorizeResult, refresh, RefreshResult } from 'react-native-app-auth';\nimport { WebView, WebViewMessageEvent } from \"react-native-webview\";\n\nexport default function Index() {\n  const dpElementOrigin = 'https://elements/uat.dailypay.com';\n  const dpElementUrl = new URL(dpElementOrigin + '/v1/available-earnings');\n  dpElementUrl.searchParams.append('client_id', 'REPLACE_WITH_YOUR_CLIENT_ID');\n  dpElementUrl.searchParams.append('implementation_id', 'REPLACE_WITH_YOUR_IMPLEMENTATION_ID');\n  // Not required but useful during development to avoid caching issues\n  dpElementUrl.searchParams.append('cache_bust', Date.now().toString());\n  const dpElementWebView = useRef<Window | null>(null);\n\n  const [inputMessageType, setInputMessageType] = useState(\"GIVE_TOKEN\");\n  const [inputMessagePayload, setInputMessagePayload] =\n    useState('{ \"token\": \"\" }');\n  const [logMessages, setLogMessages] = useState(\"\");\n\n  // Step 3: Setup Authentication\n  var dpAuthTokens: AuthorizeResult | RefreshResult | null = null;\n  const dpAuthConfig: AuthConfiguration = {\n    issuer: 'https://auth.uat.dailypay.com',\n    clientId: 'REPLACE_WITH_YOUR_OAUTH_CLIENT_ID',\n    redirectUrl: 'REPLACE_WITH_YOUR_APP_REDIRECT_URI',\n    scopes: ['user:read'],\n    serviceConfiguration: {\n      authorizationEndpoint: 'https://auth.uat.dailypay.com/oauth2/auth',\n      tokenEndpoint: 'https://auth.uat.dailypay.com/oauth2/token',\n    },\n  };\n\n  const dpAuthenticateUser = async () => {\n    try {\n      const dpAuthTokens: AuthorizeResult = await authorize(dpAuthConfig);\n      console.log('Authorization successful:', dpAuthTokens);\n      // Save token in secure storage\n      await SecureStore.setItemAsync('dpAuthTokens', JSON.stringify(dpAuthTokens));\n      // Send token to WebView\n      sendMessageToElement('GIVE_TOKEN', { token: dpAuthTokens.accessToken });\n    } catch (error) {\n      console.error('Authorization failed:', error);\n      dpAuthTokens = null;\n      // Handle authentication errors\n    }      \n  };\n  \n  const handleExtNeedAuth = async () => {\n    // Check secure storage for existing tokens\n    let dpAuthTokensString = await SecureStore.getItemAsync('dpAuthTokens');\n    if (dpAuthTokensString) {\n      dpAuthTokens = JSON.parse(dpAuthTokensString);\n      console.log('Found existing tokens:', dpAuthTokens);\n      // Check if token is expired\n      if (dpAuthTokens && dpAuthTokens.refreshToken && Date.parse(dpAuthTokens.accessTokenExpirationDate) < Date.now()) {\n        try{\n          dpAuthTokens = await refresh(dpAuthConfig, {\n            refreshToken: dpAuthTokens.refreshToken,\n          });\n          console.log('Token refresh successful:', dpAuthTokens);\n          await SecureStore.setItemAsync('dpAuthTokens', JSON.stringify(dpAuthTokens));\n        } catch (error) {\n          console.warn('Token refresh failed:', error);\n          dpAuthTokens = null;\n          dpAuthenticateUser();\n        };\n      };\n    } else {\n      console.log('No tokens found, initiating login.');\n      dpAuthenticateUser();\n    };\n    if (dpAuthTokens) {\n      console.log(dpAuthTokens)\n      sendMessageToElement('GIVE_TOKEN', { token: dpAuthTokens.accessToken });\n    } else {\n      console.warn('No valid tokens available, user needs to log in.');\n    };\n  };\n  // Step 3 End  \n    \n  // Step 2: Setup Communications: Event/Message Handling\n  // Step 2a: Send Event to Elements\n  const sendMessageToElement = (type: string, payload: object) => {\n    const message = { type: type, payload: payload };\n    if (dpElementWebView.current) {\n      dpElementWebView.current.postMessage(JSON.stringify(message), dpElementOrigin);\n      setLogMessages(\n        (prevMessages) =>\n          \"Sent: \" + JSON.stringify(message) + \"\\n\" + prevMessages,\n      );\n    }\n  };\n\n  // Step 2b: Listen for events from Elements\n  const handleMessageFromElement = (event: WebViewMessageEvent) => {\n    const receivedEvent = event.nativeEvent;\n    // Log the raw event for debugging and illustration\n    console.log(\"Raw event received:\", receivedEvent);\n    // It is crucial to verify the origin of the message for security reasons.\n    if (receivedEvent.url.startsWith(dpElementOrigin) === false) {\n      console.warn(\"Received message from unknown origin:\", receivedEvent.url);\n      return;\n    }\n    // Parse the received data - it should be a JSON formatted string\n    let receivedMessage;\n    try {\n      receivedMessage = JSON.parse(receivedEvent.data);\n    } catch (e) {\n      console.error(\"Invalid JSON in payload input:\", e);\n      return;\n    }\n    console.log(\"Message from WebView:\", receivedMessage);\n    if (receivedMessage && receivedMessage.type) {\n      setLogMessages(\n        (prevMessages) =>\n          \"Received: \" + JSON.stringify(receivedMessage) + \"\\n\" + prevMessages,\n      );\n      switch (receivedMessage.type) {\n        case \"DAILYPAY_CARD_TOKENIZE_RESPONSE\":\n          console.log(\"DAILYPAY_CARD_TOKENIZE_RESPONSE received: \", receivedMessage.success);\n          console.log(\"DAILYPAY_CARD_TOKENIZE_RESPONSE received: \", receivedMessage.response);\n          // Call API create account function\n          break;\n        case \"EXT_LOG\":\n          // Log if needed\n          console.log(\"EXT_LOG received: \", receivedMessage.payload);\n          break;\n        case \"EXT_NEED_AUTH\":\n          console.log(\"EXT_NEED_AUTH received: \", receivedMessage.payload);\n          handleExtNeedAuth();\n          break;\n        default:\n          console.log(\"Unhandled event type: \", receivedMessage.type);\n      }\n    }\n  };\n  // Step 2 End\n\n  return (\n    // Step 1: Setup a \"web view\"\n    <View style={styles.container}>\n      <Text style={styles.text}>DailyPay Elements</Text>\n      <View style={styles.webview}>\n        <WebView\n          cacheEnabled={false} // Disable caching for development\n          ref={dpElementWebView}\n          source={{ uri: dpElementUrl.toString() }}\n          style={{ flex: 1 }}\n          onMessage={handleMessageFromElement}\n          domStorageEnabled={true}  // [!code highlight]\n          javaScriptEnabled={true}  // [!code highlight]\n        />\n      </View>\n      <View style={{ height: 100, margin: 10, flex: 1 }}>\n        <Text style={styles.text}>Log:</Text>\n        <ScrollView contentContainerStyle={{ flexGrow: 1 }}>\n          <Text style={styles.text}>{logMessages}</Text>\n        </ScrollView>\n      </View>\n      <View>\n        <Text style={styles.text}>Type:</Text>\n        <TextInput\n          style={styles.input}\n          value={inputMessageType}\n          onChangeText={setInputMessageType}\n        />\n        <Text style={styles.text}>Payload (JSON):</Text>\n        <TextInput\n          style={styles.input}\n          value={inputMessagePayload}\n          onChangeText={setInputMessagePayload}\n        />\n        <Button\n          title=\"Send Message\"\n          onPress={() =>\n            sendMessageToElement(inputMessageType, JSON.parse(inputMessagePayload))\n          }\n        />\n      </View>\n    </View>\n    // Step 1 End\n  );\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: \"#25292e\",\n    justifyContent: \"center\",\n    alignItems: \"center\",\n  },\n  input: {\n    height: 40,\n    borderWidth: 1,\n    padding: 10,\n    width: 200,\n    backgroundColor: \"#fff\",\n  },\n  text: {\n    color: \"#fff\",\n  },\n  webview: {\n    width: 380,\n    height: 180,\n    borderRadius: 10,\n    overflow: 'hidden',\n  },\n});\n","wrapContents":true},"children":[]}]},"headings":[{"value":"Enabling Elements in React Native","id":"enabling-elements-in-react-native","depth":1},{"value":"Step 1. Set Up a Web View","id":"step-1-set-up-a-web-view","depth":2},{"value":"Web View Sample","id":"web-view-sample","depth":4},{"value":"Step 2. Set Up Event/Message Handling","id":"step-2-set-up-eventmessage-handling","depth":2},{"value":"Sending Events","id":"sending-events","depth":3},{"value":"Send Message Sample Code","id":"send-message-sample-code","depth":4},{"value":"Listening for Events","id":"listening-for-events","depth":3},{"value":"Receive Message Sample Code","id":"receive-message-sample-code","depth":4},{"value":"Step 3. Set Up User Authentication (Optional)","id":"step-3-set-up-user-authentication-optional","depth":2},{"value":"Full Sample Code","id":"full-sample-code","depth":2}],"frontmatter":{"seo":{"title":"Enabling Elements in React Native"}},"lastModified":"2026-07-14T14:30:25.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/rest/elements/developer-guide/react-native","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}