useTaxKit
useTaxKit() returns the live state and actions of the embedded kit. Call it from any component nested inside <TaxKitProvider>. State is synced from the iframe via post-robot — your components re-render when the iframe reports new status, sync progress, or errors.
import { useTaxKit } from '@cointracker/tax-kit';
function TaxCenter() {
const { open, taxKitStatus, isSyncingTransactions, errors } = useTaxKit();
// …
}
Return shape
useTaxKit() returns a TaxKitContext object.
Actions
open() => voidOpens the Tax Kit modal/overlay.
close() => voidCloses the Tax Kit modal/overlay.
disconnectUser() => Promise<boolean>Disconnects the user from CoinTracker and resets the kit to its empty state. Returns true on success, false on failure (network error, iframe not ready, etc.).
navigateBack() => Promise<void>Simulates pressing the back button inside the iframe. Useful when you want to surface a parent-side back affordance that drives iframe navigation.
getTaxFormUrl() => Promise<string | null>Returns a URL where the user's generated tax form can be downloaded. Returns null if no form is available yet (e.g. cost basis still calculating).
State
isTaxKitOpenbooleantrue while the iframe modal/overlay is open.
isTaxKitLoadingbooleantrue while the iframe is still computing the initial status. Use this to gate UI that depends on taxKitStatus.
isSyncingTransactionsbooleantrue while the iframe is syncing transactions to the partner.
lastSyncUpdatedTimestampnumber | nullTimestamp (ms since epoch) of the last sync update, or null if no sync has happened yet.
numberOfConnectionsnumber | nullNumber of wallets/exchanges the user has connected. null while loading.
taxKitStatusTaxKitStatusInfo | nullCurrent status object: { status, title, description, actionLabel }. null while loading. See Status lifecycle for every possible status value and what it means.
errorsTaxKitError[]Array of errors encountered during sync or authentication. Always an array (may be empty). See Errors for the full enum.
Example: full status display
import { useTaxKit, TaxKitError } from '@cointracker/tax-kit';
function TaxKitCard() {
const {
open,
taxKitStatus,
isTaxKitLoading,
isSyncingTransactions,
numberOfConnections,
errors,
} = useTaxKit();
if (isTaxKitLoading) return <Spinner />;
if (errors.includes(TaxKitError.AuthenticationError)) {
return <Error>Re-authentication required. Please reload.</Error>;
}
return (
<Card>
<h2>{taxKitStatus?.title ?? 'Tax Kit'}</h2>
<p>{taxKitStatus?.description}</p>
{isSyncingTransactions && <Badge>Syncing…</Badge>}
<button onClick={open}>
{taxKitStatus?.actionLabel ??
(numberOfConnections ? 'Open Tax Kit' : 'Get started')}
</button>
</Card>
);
}
Example: gated UI
function ExportButton() {
const { taxKitStatus, getTaxFormUrl } = useTaxKit();
if (taxKitStatus?.status !== 'SYNCED') return null;
return (
<button
onClick={async () => {
const url = await getTaxFormUrl();
if (url) window.open(url, '_blank', 'noopener');
}}
>
Download tax form
</button>
);
}
Rules
useTaxKit()must be called inside a<TaxKitProvider>. Calling it outside the provider throws.- The hook re-renders on every state update — wrap derived values in
useMemoif they're expensive. - All action functions (
open,close, etc.) are stable across renders — safe to use in dependency arrays.
State persistence
State persists across open ↔ close cycles — closing the modal doesn't reset taxKitStatus, numberOfConnections, or errors. Those values reflect the iframe's view of the user's CoinTracker state, not the modal's visibility. The values only reset when:
- The component tree unmounts (e.g. user navigates away to a route without the provider).
- The user is disconnected via
disconnectUser(). - A fresh page load occurs.
If you need to read state from outside React render (e.g. an analytics handler that fires from a global event), import the underlying store directly:
import { useTaxKitStore } from '@cointracker/tax-kit';
window.addEventListener('beforeunload', () => {
const { taxKitStatus, numberOfConnections } = useTaxKitStore.getState();
analytics.track('tax_kit_session_end', {
final_status: taxKitStatus?.status,
connections: numberOfConnections,
});
});
.getState() works outside the React render cycle; the hook does not.