React

@solana/react pubblica un client Kit nell'albero dei componenti tramite un unico provider; i hook leggono da esso dati RPC, sottoscrizioni e stato del wallet. I hook per il wallet del browser si trovano in @solana/kit-plugin-wallet/react e leggono lo stesso provider — non è necessario un provider wallet separato.

Installazione

Terminal
$
npm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-wallet @solana/react

Costruire il client

Costruisci il client una sola volta, a livello di modulo, al di fuori dell'albero React. Nel browser, walletSigner rende il wallet connesso sia il pagatore delle commissioni che l'identità.

client.ts
import { createClient } from "@solana/kit";
import { solanaRpc } from "@solana/kit-plugin-rpc";
import { walletSigner } from "@solana/kit-plugin-wallet";
export const client = createClient()
.use(walletSigner({ chain: "solana:devnet" }))
.use(solanaRpc({ rpcUrl: "https://api.devnet.solana.com" }));
export type AppClient = Awaited<typeof client>;

walletSigner aggiunge client.wallet (discovery e connessione Wallet Standard), mentre solanaRpc aggiunge client.rpc e il metodo helper client.sendTransaction. Esporta il tipo del client racchiuso in Awaited<> in modo che rimanga corretto se in seguito aggiungi un plugin che si risolve in modo asincrono, e passa quell'AppClient a ogni chiamata useClient.

Avvolgi il tuo albero una sola volta

ClientProvider pubblica il client. I hook per i dati (useRequest, useSubscription, useTrackedData) lo leggono tramite useClient. I hook per il wallet illustrati di seguito richiedono che lo stesso client venga passato esplicitamente come primo argomento.

providers.tsx
"use client";
import { ClientProvider } from "@solana/react";
import { client } from "./client";
export function Providers({ children }: { children: React.ReactNode }) {
return <ClientProvider client={client}>{children}</ClientProvider>;
}

Hook per il wallet

Gli hook per il wallet richiedono un client con un plugin wallet installato (ad es. walletSigner). Recuperalo tramite useClient<AppClient>() e passalo come primo argomento di ciascun hook — in questo modo l'app rimane completamente tipizzata end-to-end anziché affidarsi a ricerche nel contesto.

  • useWallets(client) — Wallet Standard scoperti per la chain del client.
  • useWalletStatus(client)"pending" | "disconnected" | "connecting" | "connected" | "disconnecting" | "reconnecting".
  • useConnectedWallet(client){ account, signer, wallet } oppure null. signer è null per i wallet in sola lettura.
  • useConnect(client) / useDisconnect(client) — restituiscono un ActionResult il cui dispatch (e dispatchAsync) esegue l'azione e i cui isRunning, status, data, error e reset ne tracciano il risultato.
"use client";
import {
useConnect,
useConnectedWallet,
useDisconnect,
useWallets,
useWalletStatus
} from "@solana/kit-plugin-wallet/react";
import { useClient } from "@solana/react";
import type { AppClient } from "./client";
function WalletPanel() {
const client = useClient<AppClient>();
const status = useWalletStatus(client);
const wallets = useWallets(client);
const connected = useConnectedWallet(client);
const connect = useConnect(client);
const disconnect = useDisconnect(client);
if (status === "pending") return null; // wait out auto-reconnect
if (connected) {
return (
<div>
<p>{connected.account.address}</p>
<button onClick={() => disconnect.dispatch()}>Disconnect</button>
</div>
);
}
return (
<div>
{wallets.map((wallet) => (
<button
key={wallet.name}
disabled={connect.isRunning}
onClick={() => connect.dispatch(wallet)}
>
Connect {wallet.name}
</button>
))}
</div>
);
}

Inviare una transazione

useClient restituisce lo stesso client che hai pubblicato. Costruisci le istruzioni con un client di programma generato e inviale tramite client.sendTransaction.

"use client";
import { address, lamports } from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import { useClient } from "@solana/react";
import { useConnectedWallet } from "@solana/kit-plugin-wallet/react";
import type { AppClient } from "./client";
function SendSol({ destination }: { destination: string }) {
const client = useClient<AppClient>();
const connected = useConnectedWallet(client);
async function handleSend() {
if (!connected?.signer) return;
const transfer = getTransferSolInstruction({
source: connected.signer,
destination: address(destination),
amount: lamports(10_000_000n) // 0.01 SOL
});
const result = await client.sendTransaction([transfer]);
console.log("sent", result.context.signature);
}
return (
<button disabled={!connected?.signer} onClick={handleSend}>
Send 0.01 SOL
</button>
);
}

Passare il tipo AppClient esportato a useClient fornisce all'hook il client completo esteso dai plugin, in modo che client.rpc e client.sendTransaction siano tipizzati.

Leggere i dati

@solana/react include hook che leggono tramite il client:

  • useRequest(source) — lettura RPC singola; restituisce { data, error, status, refresh }.
  • useSubscription(source) — una sottoscrizione live; restituisce { data, error, reconnect, status }.
  • useTrackedData(spec) — un valore inizializzato tramite RPC e mantenuto aggiornato da una sottoscrizione.
"use client";
import { address } from "@solana/kit";
import { useClient, useRequest } from "@solana/react";
import { useMemo } from "react";
import type { AppClient } from "./client";
function Balance({ owner }: { owner: string }) {
const client = useClient<AppClient>();
const source = useMemo(
() => client.rpc.getBalance(address(owner)),
[client, owner]
);
const { data, status, refresh } = useRequest(source);
if (status === "fetching") return <p>Loading…</p>;
if (status === "error") return <p role="alert">RPC error</p>;
return (
<div>
<p>Lamports: {data?.value.toString()}</p>
<button onClick={() => refresh()}>Refresh</button>
</div>
);
}

Memorizza la sorgente (con useMemo, o useCallback per una funzione) in modo che l'hook esegua un nuovo fetch solo quando i suoi input cambiano, anziché ad ogni render.

Per il caching e la rivalidazione, i sottopercorsi @solana/react/swr e @solana/react/query racchiudono gli stessi hook per SWR e TanStack Query.

Pattern comuni per gli sviluppatori Solana

  • Un solo provider: ClientProvider è l'unico provider di cui hai bisogno; ottieni il client con useClient<AppClient>() e passalo agli hook del wallet.
  • Compatibile con i Server Component: contrassegna con "use client" solo i componenti foglia che chiamano hook; le letture lato server possono utilizzare un client RPC Kit senza wallet.
  • Testing: pubblica un client simulato tramite ClientProvider per simulare wallet e risposte RPC.

Due famiglie di hook, stessi nomi

useSignIn e useSignMessage esistono sia in @solana/react (accettano un argomento UiWalletAccount) sia in @solana/kit-plugin-wallet/react (accettano il client, restituiscono un ActionResult). Utilizza le versioni di @solana/kit-plugin-wallet/react con il pattern basato sul client illustrato sopra; i vecchi hook wallet di @solana/react sono in fase di sostituzione.

Abbina questa guida alla panoramica del client Kit per comprendere il client da cui ogni hook legge.

Is this page helpful?

Indice dei contenuti

Modifica pagina
© 2026 Solana Foundation. Tutti i diritti riservati.