@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
$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à.
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.
"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 }oppurenull.signerènullper i wallet in sola lettura.useConnect(client)/useDisconnect(client)— restituiscono unActionResultil cuidispatch(edispatchAsync) esegue l'azione e i cuiisRunning,status,data,erroreresetne 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-reconnectif (connected) {return (<div><p>{connected.account.address}</p><button onClick={() => disconnect.dispatch()}>Disconnect</button></div>);}return (<div>{wallets.map((wallet) => (<buttonkey={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 conuseClient<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
ClientProviderper 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?