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 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 an active UI key
  • Basic understanding of React hooks (useEffect, useRef, useState)

5-minute minimal example​

This simple example shows our 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 app. This component manages 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(import.meta.env.VITE_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 (legacy)​

Create React App is legacy

Create React App is no longer maintained. For new projects, use Vite or a meta-framework such as Next.js or Remix.

For existing 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>

In CRA projects, initialize the SDK using process.env.REACT_APP_WEAVR_UI_KEY instead of import.meta.env.VITE_WEAVR_UI_KEY.

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 (Vite example):

// 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>;
};
Avoid repeated init() calls

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

Next steps​