Skip to main content

Additional React Hooks

Beyond the core useCardanoDevKit and useWallet hooks, Cardano DevKit provides additional hooks for specific use cases.

useTransaction

Hook for building and submitting transactions.

import { useCardanoDevKit, useTransaction } from 'cardano-devkit';

function TransactionBuilder() {
const { lucid } = useCardanoDevKit({ network: 'Preprod' });
const {
buildTx,
signAndSubmit,
txHash,
status,
error,
isBuilding,
isSubmitting,
reset,
} = useTransaction(lucid);

const handleSend = async () => {
// Build transaction
const tx = await buildTx(builder =>
builder
.pay.ToAddress("addr_test1...", { lovelace: 5000000n })
.attachMetadata(674, { msg: ["Hello!"] })
);

// Sign and submit
const hash = await signAndSubmit(tx);
console.log("Submitted:", hash);
};

return (
<div>
<button onClick={handleSend} disabled={isBuilding || isSubmitting}>
{isSubmitting ? 'Submitting...' : 'Send 5 ADA'}
</button>
{txHash && <p>Transaction: {txHash}</p>}
{status && <p>Status: {status}</p>}
{error && <p>Error: {error.message}</p>}
</div>
);
}

Return Value

interface UseTransactionReturn {
// State
txHash: string | null;
status: 'idle' | 'building' | 'signing' | 'submitting' | 'submitted' | 'confirmed' | 'error';
error: Error | null;
isBuilding: boolean;
isSubmitting: boolean;

// Actions
buildTx: (builder: (tx: TxBuilder) => TxBuilder) => Promise<Transaction>;
signAndSubmit: (tx: Transaction) => Promise<string>;
waitForConfirmation: (txHash?: string, timeout?: number) => Promise<boolean>;
reset: () => void;
}

useAssets

Hook for querying and managing native assets.

import { useCardanoDevKit, useWallet, useAssets } from 'cardano-devkit';

function AssetDisplay() {
const { lucid } = useCardanoDevKit({ network: 'Preprod' });
const { address } = useWallet(lucid);
const {
assets,
nfts,
fungibleTokens,
isLoading,
refresh,
getAssetDetails,
} = useAssets(lucid, address);

if (isLoading) return <div>Loading assets...</div>;

return (
<div>
<h2>Your NFTs ({nfts.length})</h2>
{nfts.map(nft => (
<div key={nft.unit}>
<p>{nft.name}</p>
<img src={nft.image} alt={nft.name} />
</div>
))}

<h2>Tokens</h2>
{fungibleTokens.map(token => (
<div key={token.unit}>
<p>{token.name}: {token.quantity.toString()}</p>
</div>
))}

<button onClick={refresh}>Refresh</button>
</div>
);
}

Return Value

interface UseAssetsReturn {
// State
assets: Asset[];
nfts: NFTAsset[];
fungibleTokens: TokenAsset[];
isLoading: boolean;
error: Error | null;

// Actions
refresh: () => Promise<void>;
getAssetDetails: (unit: string) => Promise<AssetDetails | null>;
hasAsset: (policyId: string, assetName?: string) => boolean;
getAssetQuantity: (unit: string) => bigint;
}

interface Asset {
unit: string;
policyId: string;
assetName: string;
quantity: bigint;
}

interface NFTAsset extends Asset {
name?: string;
image?: string;
description?: string;
metadata?: Record<string, unknown>;
}

useUTxOs

Hook for querying UTxOs at addresses or scripts.

import { useCardanoDevKit, useUTxOs } from 'cardano-devkit';

function UTxOViewer() {
const { lucid } = useCardanoDevKit({ network: 'Preprod' });
const {
utxos,
totalLovelace,
isLoading,
refresh,
findByAsset,
findByMinAda,
} = useUTxOs(lucid, "addr_test1...");

if (isLoading) return <div>Loading UTxOs...</div>;

const largeUtxos = findByMinAda(10000000n); // UTxOs with >= 10 ADA

return (
<div>
<h2>UTxOs ({utxos.length})</h2>
<p>Total: {formatLovelace(totalLovelace)} ADA</p>

<h3>Large UTxOs ({largeUtxos.length})</h3>
{largeUtxos.map(utxo => (
<div key={`${utxo.txHash}#${utxo.outputIndex}`}>
<p>Hash: {utxo.txHash}</p>
<p>Index: {utxo.outputIndex}</p>
<p>Value: {formatLovelace(utxo.assets.lovelace)} ADA</p>
</div>
))}

<button onClick={refresh}>Refresh</button>
</div>
);
}

Return Value

interface UseUTxOsReturn {
// State
utxos: UTxO[];
totalLovelace: bigint;
isLoading: boolean;
error: Error | null;

// Actions
refresh: () => Promise<void>;

// Queries
findByAsset: (policyId: string, assetName?: string) => UTxO[];
findByMinAda: (minLovelace: bigint) => UTxO[];
findByDatum: (datumHash: string) => UTxO[];
}

useNetworkStatus

Hook for monitoring network connectivity and status.

import { useCardanoDevKit, useNetworkStatus } from 'cardano-devkit';

function NetworkMonitor() {
const { lucid } = useCardanoDevKit({ network: 'Preprod' });
const {
isConnected,
latency,
blockHeight,
epoch,
slot,
syncProgress,
lastUpdate,
refresh,
} = useNetworkStatus(lucid);

return (
<div className={isConnected ? 'connected' : 'disconnected'}>
<h2>Network Status</h2>
<p>Status: {isConnected ? '🟢 Connected' : '🔴 Disconnected'}</p>
<p>Latency: {latency}ms</p>
<p>Block: {blockHeight?.toLocaleString()}</p>
<p>Epoch: {epoch}</p>
<p>Slot: {slot?.toLocaleString()}</p>
<p>Sync: {(syncProgress * 100).toFixed(2)}%</p>
<p>Updated: {lastUpdate?.toLocaleTimeString()}</p>
<button onClick={refresh}>Refresh</button>
</div>
);
}

Return Value

interface UseNetworkStatusReturn {
// State
isConnected: boolean;
latency: number | null;
blockHeight: number | null;
epoch: number | null;
slot: number | null;
syncProgress: number;
lastUpdate: Date | null;
error: Error | null;

// Actions
refresh: () => Promise<void>;
}

Combining Hooks

Here's an example combining multiple hooks:

import {
useCardanoDevKit,
useWallet,
useTransaction,
useAssets,
useNetworkStatus,
formatLovelace,
} from 'cardano-devkit';

function CompleteDApp() {
const { lucid, network, switchNetwork } = useCardanoDevKit({ network: 'Preprod' });
const { address, balance, isConnected, connect } = useWallet(lucid);
const { buildTx, signAndSubmit, txHash, status } = useTransaction(lucid);
const { nfts, fungibleTokens } = useAssets(lucid, address);
const { isConnected: networkOk, blockHeight } = useNetworkStatus(lucid);

if (!networkOk) {
return <div>Connecting to network...</div>;
}

if (!isConnected) {
return (
<div>
<p>Network: {network} (Block #{blockHeight})</p>
<button onClick={() => connect('browser', 'nami')}>
Connect Wallet
</button>
</div>
);
}

const handleMint = async () => {
const tx = await buildTx(builder =>
builder
.mintAssets({ [policyId + assetName]: 1n })
.attachMintingPolicy(mintingPolicy)
);
await signAndSubmit(tx);
};

return (
<div>
<header>
<p>Network: {network}</p>
<p>Balance: {formatLovelace(balance)} ADA</p>
<p>NFTs: {nfts.length}</p>
</header>

<main>
<button onClick={handleMint} disabled={status === 'submitting'}>
Mint NFT
</button>
{txHash && <p>TX: {txHash}</p>}
</main>

<button onClick={() => switchNetwork('Preview')}>
Switch to Preview
</button>
</div>
);
}

Performance Tips

  1. Avoid re-renders: Use useMemo and useCallback with hook values
  2. Batch updates: Use the transaction builder to batch multiple operations
  3. Lazy loading: Only fetch assets/UTxOs when needed
  4. Debounce refreshes: Don't call refresh() on every render
// Good: Memoize expensive computations
const largeUtxos = useMemo(
() => utxos.filter(u => u.assets.lovelace > 10000000n),
[utxos]
);

// Good: Debounce refresh calls
const debouncedRefresh = useMemo(
() => debounce(refresh, 1000),
[refresh]
);