Skip to main content
All hooks require being inside a NearProvider. They will throw an error if used outside the provider context.

Read Hooks

These hooks fetch data from the blockchain. They all return a consistent shape:
interface ViewResult<T> {
  data: T | undefined          // The fetched data
  error: Error | undefined     // Any error that occurred
  isLoading: boolean           // Whether fetch is in progress
  refetch: () => Promise<void> // Manually trigger a refetch
}

useView

params
UseViewParams
required
Call any view method on a NEAR smart contract.
import { useView } from "@near-kit/react"

function Messages() {
  const { data, isLoading, error, refetch } = useView<{ limit: number }, Message[]>({
    contractId: "guestbook.near",
    method: "get_messages",
    args: { limit: 10 },
  })

  if (isLoading) return <p>Loading...</p>
  if (error) return <p>Error: {error.message}</p>

  return (
    <div>
      {data?.map((msg) => <p key={msg.id}>{msg.text}</p>)}
      <button onClick={refetch}>Refresh</button>
    </div>
  )
}
When args change (by reference or value), the hook automatically refetches. Use useMemo for computed args to prevent unnecessary refetches.

useBalance

params
UseBalanceParams
required
Fetch an account’s NEAR balance as a formatted string.
import { useBalance } from "@near-kit/react"

function WalletBalance({ accountId }: { accountId: string }) {
  const { data: balance, isLoading, refetch } = useBalance({ accountId })

  if (isLoading) return <span>...</span>

  return (
    <div>
      <span>{balance}</span> {/* "10.50 NEAR" */}
      <button onClick={refetch}></button>
    </div>
  )
}
Returns a human-readable string like "10.50 NEAR". For raw BigInt values, use useNear() and call near.getAccountDetails() directly.

useAccountExists

params
UseAccountExistsParams
required
Check if a NEAR account exists on the network.
import { useAccountExists } from "@near-kit/react"

function AccountChecker() {
  const [input, setInput] = useState("")
  const { data: exists, isLoading } = useAccountExists({
    accountId: input,
    enabled: input.length > 0,
  })

  return (
    <div>
      <input value={input} onChange={(e) => setInput(e.target.value)} />
      {isLoading && <span>Checking...</span>}
      {exists === true && <span>✓ Account exists</span>}
      {exists === false && <span>✗ Account not found</span>}
    </div>
  )
}

useAccount

(no params)
Get the current connected account state from the Near client.
Returns:
interface AccountState {
  accountId: string | undefined  // The connected account ID
  isConnected: boolean           // Whether any account is connected
  isLoading: boolean             // Whether state is being fetched
  refetch: () => Promise<void>   // Refresh account state
}
import { useAccount } from "@near-kit/react"

function Header() {
  const { accountId, isConnected, isLoading } = useAccount()

  if (isLoading) return <span>Loading...</span>
  if (!isConnected) return <button>Connect Wallet</button>

  return <span>Connected: {accountId}</span>
}
This hook accesses internal Near client state. The account is derived from whatever signer was configured (wallet adapter, private key, or keystore).

Mutation Hooks

These hooks modify blockchain state. They return a consistent shape:
interface MutationResult<TArgs, TResult> {
  mutate: (args: TArgs) => Promise<TResult>  // Execute the mutation
  data: TResult | undefined                  // Last successful result
  error: Error | undefined                   // Any error from last call
  isPending: boolean                         // Whether mutation is in progress
  isSuccess: boolean                         // Whether last call succeeded
  isError: boolean                           // Whether last call failed
  reset: () => void                          // Reset mutation state
}

useCall

params
UseCallParams
required
Call a change method on a NEAR smart contract.
Cache invalidation not included. After a mutation, related queries won’t automatically refetch. For apps where mutations should update the UI, use React Query with invalidateQueries() instead.
import { useCall } from "@near-kit/react"

function IncrementButton() {
  const { mutate, isPending, isError, error } = useCall({
    contractId: "counter.testnet",
    method: "increment",
  })

  return (
    <div>
      <button onClick={() => mutate({})} disabled={isPending}>
        {isPending ? "Processing..." : "Increment"}
      </button>
      {isError && <p>Error: {error?.message}</p>}
    </div>
  )
}
OptionTypeDescription
gasstringGas limit (e.g., "30 Tgas", "100 Tgas")
attachedDepositstringNEAR to attach (e.g., "1 NEAR", "0.01 NEAR")
waitUntil"INCLUDED" | "EXECUTED" | "FINAL"When to resolve the promise

useSend

(no params)
Send NEAR tokens to another account.
Returns a mutate function with signature:
mutate: (to: string, amount: AmountInput) => Promise<void>
Where AmountInput is "10 NEAR" | "1000 yocto" | bigint
import { useSend } from "@near-kit/react"

function SendForm() {
  const { mutate: send, isPending, isSuccess, error } = useSend()
  const [recipient, setRecipient] = useState("")
  const [amount, setAmount] = useState("")

  const handleSend = async () => {
    try {
      await send(recipient, `${amount} NEAR`)
    } catch (err) {
      // Error is also available via `error` state
      console.error("Transfer failed:", err)
    }
  }

  return (
    <div>
      <input
        placeholder="Recipient (e.g., bob.near)"
        value={recipient}
        onChange={(e) => setRecipient(e.target.value)}
      />
      <input
        placeholder="Amount in NEAR"
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
      />
      <button onClick={handleSend} disabled={isPending}>
        {isPending ? "Sending..." : "Send NEAR"}
      </button>
      {isSuccess && <p>Transfer complete!</p>}
      {error && <p>Error: {error.message}</p>}
    </div>
  )
}

Utility Hooks

useNear

Access the raw Near client instance for advanced operations:
import { useNear } from "@near-kit/react"

function AdvancedTransaction() {
  const near = useNear()

  const handleBatch = async () => {
    // Full access to the transaction builder
    await near
      .transaction("alice.near")
      .createAccount("sub.alice.near")
      .transfer("sub.alice.near", "5 NEAR")
      .addKey("sub.alice.near", "ed25519:...")
      .send()
  }

  return <button onClick={handleBatch}>Create Subaccount</button>
}

useContract

contractId
string
required
Get a fully-typed contract interface using near.contract<T>().
import { useContract } from "@near-kit/react"
import type { Contract } from "near-kit"

// Define your contract's type signature
type FungibleToken = Contract<{
  view: {
    ft_balance_of: (args: { account_id: string }) => Promise<string>
    ft_metadata: () => Promise<{ name: string; symbol: string; decimals: number }>
  }
  call: {
    ft_transfer: (args: { receiver_id: string; amount: string }) => Promise<void>
  }
}>

function TokenBalance({ accountId }: { accountId: string }) {
  const token = useContract<FungibleToken>("usdt.tether-token.near")
  const [balance, setBalance] = useState<string>()

  useEffect(() => {
    token.view.ft_balance_of({ account_id: accountId }).then(setBalance)
  }, [token, accountId])

  return <p>Balance: {balance}</p>
}
For reactive data fetching with contracts, combine useContract with useEffect or integrate with React Query. See Data Fetching for patterns.