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.