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
- Avoid re-renders: Use
useMemoanduseCallbackwith hook values - Batch updates: Use the transaction builder to batch multiple operations
- Lazy loading: Only fetch assets/UTxOs when needed
- 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]
);