Skip to main content

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() => void

Opens the Tax Kit modal/overlay.

close() => void

Closes 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

isTaxKitOpenboolean

true while the iframe modal/overlay is open.

isTaxKitLoadingboolean

true while the iframe is still computing the initial status. Use this to gate UI that depends on taxKitStatus.

isSyncingTransactionsboolean

true while the iframe is syncing transactions to the partner.

lastSyncUpdatedTimestampnumber | null

Timestamp (ms since epoch) of the last sync update, or null if no sync has happened yet.

numberOfConnectionsnumber | null

Number of wallets/exchanges the user has connected. null while loading.

taxKitStatusTaxKitStatusInfo | null

Current 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 useMemo if they're expensive.
  • All action functions (open, close, etc.) are stable across renders — safe to use in dependency arrays.

State persistence

State persists across openclose 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.