React Integration Guide

This guide covers everything you need to integrate io.Connect into your React applications, from initialization to advanced hook patterns.

Installation

Install packages
# For Browser Platform (host/main app)
npm install @interopio/browser-platform @interopio/react-hooks

# For Browser Client (child apps)
npm install @interopio/browser @interopio/react-hooks

# For Desktop apps
npm install @interopio/desktop @interopio/react-hooks

IOConnectProvider

The IOConnectProvider component initializes the io.Connect API and makes it available to all child components via React context.

Browser Platform Setup

main.tsx (Platform app)
import ReactDOM from "react-dom/client";
import IOBrowserPlatform from "@interopio/browser-platform";
import { IOConnectProvider } from "@interopio/react-hooks";
import type { IOConnectInitSettings } from "@interopio/react-hooks";
import App from "./App";

const settings: IOConnectInitSettings = {
  browserPlatform: {
    factory: IOBrowserPlatform,
    config: {
      licenseKey: import.meta.env.VITE_IOCONNECT_LICENSE_KEY,
    },
  },
};

// Important: Remove React.StrictMode to prevent double initialization
ReactDOM.createRoot(document.getElementById("root")!).render(
  <IOConnectProvider settings={settings} fallback={<div>Loading...</div>}>
    <App />
  </IOConnectProvider>
);
No StrictModeDo not wrap IOConnectProvider with React.StrictMode. StrictMode causes double-execution of effects, which will attempt to initialize the io.Connect Platform twice and fail.

Browser Client Setup

main.tsx (Client app)
import ReactDOM from "react-dom/client";
import IOBrowser from "@interopio/browser";
import { IOConnectProvider } from "@interopio/react-hooks";
import type { IOConnectInitSettings } from "@interopio/react-hooks";
import App from "./App";

const settings: IOConnectInitSettings = {
  browser: {
    factory: IOBrowser,
  },
};

ReactDOM.createRoot(document.getElementById("root")!).render(
  <IOConnectProvider settings={settings} fallback={<div>Connecting...</div>}>
    <App />
  </IOConnectProvider>
);

Accessing the io Object

Use React's useContext hook with IOConnectContext:

Access io object
import { useContext } from "react";
import { IOConnectContext } from "@interopio/react-hooks";

function MyComponent() {
  const io = useContext(IOConnectContext);

  // io is available here
  // io.contexts, io.channels, io.interop, etc.
}
NoteThe @interopio/react-hooks package does not export a useIOConnectContext hook. Access the io object through React's standard useContext(IOConnectContext) pattern.

useIOConnect Hook

The useIOConnect hook is designed for subscriptions and operations that need cleanup. It receives the io object as a parameter and supports returning a cleanup function.

useIOConnect for subscriptions
import { useState } from "react";
import { useIOConnect } from "@interopio/react-hooks";

interface ClientData {
  name: string;
  email: string;
}

function ClientSubscriber() {
  const [client, setClient] = useState<ClientData | null>(null);

  // Subscribe with automatic cleanup
  useIOConnect(async (io) => {
    const unsubscribe = await io.contexts.subscribe(
      "SelectedClient",
      (data: ClientData) => setClient(data)
    );
    // Return cleanup function
    return () => unsubscribe();
  }, []);

  return <div>{client?.name ?? "No client selected"}</div>;
}

Creating Callback Functions

Use useIOConnect to create memoized callbacks that have access to the io object:

useIOConnect for callbacks
const publishClient = useIOConnect((io) => async (clientId: string) => {
  await io.contexts.update("SelectedClient", {
    type: "fdc3.contact",
    id: { email: clientId },
  });
});

// Use in JSX:
<button onClick={() => publishClient("jane@example.com")}>
  Select Jane
</button>

TypeScript Patterns

Type-only Imports

When verbatimModuleSyntax is enabled in TypeScript, use import type for type-only imports:

Correct import pattern
// ✅ Correct
import type { IOConnectInitSettings } from "@interopio/react-hooks";
import { IOConnectProvider, IOConnectContext } from "@interopio/react-hooks";

// ❌ Wrong — will error with verbatimModuleSyntax
import { IOConnectInitSettings, IOConnectProvider } from "@interopio/react-hooks";

Typed State

Typed state with generics
interface Portfolio {
  totalValue: number;
  holdings: Array<{ symbol: string; quantity: number }>;
}

const [portfolio, setPortfolio] = useState<Portfolio | null>(null);

Best Practices

  • Return cleanup functions from useIOConnect and useEffect subscriptions to avoid memory leaks
  • Access the io object through useContext(IOConnectContext) in any component under the provider
  • Define explicit TypeScript interfaces for context data, interop arguments, and stream payloads
  • Use import type for type-only imports when verbatimModuleSyntax is enabled
  • The io reference is stable across re-renders — safe to use in dependency arrays
  • Unregister interop methods on component unmount to ensure clean lifecycle management