useAction

function useAction<TArgs, TResult>(fn): ActionResult<TArgs, TResult>;

Bridge an arbitrary async function into a reactive ActionResult. Each send(...) call runs the function with a fresh AbortSignal and tracks its lifecycle through React state; a second call while a first is in flight aborts the first.

fn is held in a ref that always points at the latest closure — there is no deps array to maintain. Each send(...) invokes the most recently rendered fn, so values captured inside (e.g. form state, route params) are always fresh without explicit dependency tracking. This matches the convention used by useMutation in TanStack Query and useWriteContract in wagmi. In-flight calls are unaffected — they continue with the closure they captured at dispatch time.

Type Parameters

Type ParameterDescription
TArgs extends readonly unknown[]The argument tuple send accepts; forwarded to fn after the abort signal.
TResultThe value fn resolves to on success.

Parameters

ParameterType
fn(signal, ...args) => Promise<TResult>

Returns

ActionResult<TArgs, TResult>

Example

import { useAction } from '@solana/react';
 
function PostMessageButton({ url, body }: { url: string; body: string }) {
    const { send, isRunning, error } = useAction(async (signal, content: string) => {
        const res = await fetch(url, { body: content, method: 'POST', signal });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json() as Promise<{ id: string }>;
    });
    return (
        <button disabled={isRunning} onClick={() => send(body)}>
            {isRunning ? 'Posting…' : error ? 'Retry' : 'Post'}
        </button>
    );
}

See

ActionResult

On this page