Skip to main content

React integration: getting started

This guide covers integrating Weavr Web SDK UI components with React 18+ using functional components and hooks. You'll learn the correct patterns for script loading, lifecycle management, and the four distinct component integration patterns.

Overview and quick start

Prerequisites

  • React 18.x or later with functional components
  • A Weavr account with API credentials (UI key)
  • Basic understanding of React hooks (useEffect, useRef, useState)

5-minute minimal example

This simple example shows the Weavr password input component working in a React app.

1. Add the SDK to your index.html

<!doctype html>
<html>
<head>
<script src="https://sandbox.weavr.io/app/secure/static/client.1.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>

2. Create a password input component

Create a new React component for each Weavr web component you want to use in your application. This component will manage the rendering and state of the web SDK component.

import React, { useEffect, useRef, useState } from "react";

const PasswordInput: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null);
const formRef = useRef<any>(null);

useEffect(() => {
if (!window.OpcUxSecureClient) {
console.error("Weavr SDK not loaded - check index.html script tag");
return;
}

window.OpcUxSecureClient.init(process.env.WEAVR_UI_KEY);

const form = window.OpcUxSecureClient.form();
const input = form.input("password", "password", {
placeholder: "Enter password",
});

formRef.current = form;
input.mount(containerRef.current);

// Cleanup on unmount
return () => {
try {
form.destroy();
} catch (e) {
console.warn("Error destroying form:", e);
}
};
}, []);

const handleSubmit = () => {
formRef.current?.tokenize(
(tokens: Record<string, string>) => {
console.log("Password token:", tokens.password);
// Send tokens.password to your server
},
(error: any) => {
console.error("Tokenize failed:", error);
}
);
};

return (
<form
onSubmit={(e) => {
e.preventDefault();
handleSubmit();
}}
>
<div id="password-container" ref={containerRef}></div>
<button type="submit">Submit</button>
</form>
);
};

export default PasswordInput;

Script loading

Critical requirement

The Weavr SDK must be loaded via a <script> tag in index.html. Do not import it through Vite, webpack, or any bundler.

See Framework Integration Overview for details on why this is required.

Vite configuration

Add the SDK to index.html in your project root:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Your App</title>

<!-- Weavr SDK - MUST be loaded here, not via import -->
<script src="https://sandbox.weavr.io/app/secure/static/client.1.js"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

Create React App configuration

For CRA projects, add the SDK to public/index.html:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>React App</title>

<!-- Weavr SDK -->
<script src="https://sandbox.weavr.io/app/secure/static/client.1.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>

Environment-based SDK URLs

For production deployments, use different SDK URLs per environment:

<script>
// Determine SDK URL based on environment
const sdkUrl =
window.location.hostname === "localhost"
? "https://sandbox.weavr.io/app/secure/static/client.1.js"
: "https://secure.weavr.io/app/secure/static/client.1.js";

const script = document.createElement("script");
script.src = sdkUrl;
document.head.appendChild(script);
</script>

Or use separate HTML files for each environment.

SDK initialization

Initialize the SDK once when your app starts:

// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

// Type declarations for the SDK
declare global {
interface Window {
OpcUxSecureClient: {
init: (
uiKey: string,
options?: { fonts?: Array<{ cssSrc: string }> }
) => void;
form: () => WeavrForm;
span: (type: string, token: string, options?: object) => WeavrSpan;
associate: (
token: string,
onSuccess: () => void,
onError?: (e: Error) => void
) => void;
consumer_kyc: () => {
init: (config: {
selector: string;
reference: string;
lang?: string;
onMessage?: (message: string, additionalInfo?: any) => void;
onError?: (error: string) => void;
}) => void;
};
kyb: () => {
init: (
selector: string,
auth: { reference: string },
listener: (messageType: string, payload: any) => void,
options?: { lang?: string }
) => void;
};
kyc: () => {
init: (
selector: string,
auth: { reference: string },
listener: (messageType: string, payload: any) => void,
options?: { lang?: string }
) => void;
};
};
}
}

interface WeavrForm {
input: (name: string, field: string, options?: object) => WeavrInput;
tokenize: (
resolve?: (tokens: Record<string, string>) => void,
reject?: (error: any) => void
) => void;
destroy: () => void;
}

interface WeavrInput {
mount: (element: HTMLElement | string) => void;
unmount: () => void;
destroy: () => void;
on: (event: string, callback: (data: unknown) => void) => void;
}

interface WeavrSpan {
mount: (element: HTMLElement | string) => void;
unmount: () => void;
on: (event: string, callback: (data: unknown) => void) => void;
}

// Initialize SDK
const initializeSDK = () => {
if (!window.OpcUxSecureClient) {
console.error("Weavr SDK not loaded");
return;
}

window.OpcUxSecureClient.init(import.meta.env.VITE_WEAVR_UI_KEY, {
fonts: [
{
cssSrc: "https://fonts.googleapis.com/css?family=Inter:400,500,600",
},
],
});
};

initializeSDK();

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Per-component initialization

For simpler setups, initialize in each component:

import React, { useEffect } from "react";

const MyComponent: React.FC = () => {
useEffect(() => {
if (window.OpcUxSecureClient) {
window.OpcUxSecureClient.init("your_ui_key");
}
}, []);

return <div>...</div>;
};
caution

Calling init() multiple times is safe, but wasteful. Prefer app-level initialization for larger applications.

Next steps