Skip to content

React Integration

TokenFlight is exposed publicly as <tokenflight-widget> plus the TokenFlightWidget imperative class.

Imperative API

The imperative API is the most reliable approach across React versions. Use useRef for the container and useEffect for lifecycle management:

tsx

function PaymentWidget({ wagmiConfig, theme = 'dark' }) {
  const containerRef = useRef<HTMLDivElement>(null);
  const walletAdapter = useMemo(
    () => new WagmiWalletAdapter(wagmiConfig),
    [wagmiConfig]
  );

  useEffect(() => {
    if (!containerRef.current) return;

    const widget = new TokenFlightWidget({
      container: containerRef.current,
      config: {
        toToken: { chainId: 8453, address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' },
        tradeType: 'EXACT_OUTPUT',
        amount: '100',
        theme,
      },
      walletAdapter,
      callbacks: {
        onSwapSuccess: (data) => console.log('Payment completed:', data.orderId),
        onSwapError: (error) => console.error(`[${error.code}] ${error.message}`),
      },
    });

    widget.initialize();
    return () => widget.destroy();
  }, [walletAdapter, theme]);

  return <div ref={containerRef} style={{ minHeight: 560 }} />;
}

Declarative Usage

If you prefer the custom element directly, register the widget once and use <tokenflight-widget> in JSX:

tsx

function App({ wagmiConfig }) {
  useEffect(() => {
    registerWidgetElement({
      walletAdapter: new WagmiWalletAdapter(wagmiConfig),
      callbacks: {
        onSwapSuccess: (data) => console.log('Payment completed:', data.orderId),
        onSwapError: (error) => console.error(`[${error.code}] ${error.message}`),
      },
    });
  }, [wagmiConfig]);

  return (
    <tokenflight-widget
      to-token="eip155:8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
      trade-type="EXACT_OUTPUT"
      amount="100"
      theme="dark"
    />
  );
}

For per-instance callbacks, use a ref:

tsx

registerWidgetElement();

function WidgetWithCallbacks() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    if (!ref.current) return;
    ref.current.__callbacks = {
      onSwapSuccess: (data) => console.log('Done:', data),
      onConnectWallet: () => myWalletModal.open(),
    };
  }, []);

  return (
    <tokenflight-widget
      ref={ref}
      to-token="eip155:8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
      trade-type="EXACT_OUTPUT"
      amount="100"
      theme="dark"
    />
  );
}

React JSX Caveats

In React 18 and earlier, custom-element props are usually serialized as attributes:

  • Objects cannot be passed via JSX.
  • Functions cannot be passed via JSX.
  • String and boolean HTML attributes work normally.

That is why declarative usage relies on registerWidgetElement() defaults or ref.__callbacks for non-string values.

TypeScript JSX Declarations

Add one import to get typed JSX tags for <tokenflight-widget>:

ts

Key Reminders

  • Cache adapter instances with useMemo.
  • Call destroy() in the cleanup function.
  • Recreate the widget when config changes after initialize().
  • There is no separate React wrapper package; use the public widget directly.