@solana/react publica un cliente Kit en tu árbol de componentes a través de un único proveedor; los hooks leen datos RPC, suscripciones y el estado de la billetera desde él. Los hooks de billetera del navegador viven en @solana/kit-plugin-wallet/react y leen el mismo proveedor — no existe un proveedor de billetera separado.
Instalación
$npm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-wallet @solana/react
Construir el cliente
Construye el cliente una sola vez, en el ámbito del módulo, fuera del árbol de React. En el navegador, walletSigner convierte la billetera conectada en el pagador de comisiones y la identidad.
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 añade client.wallet (descubrimiento y conexión con Wallet Standard), y solanaRpc añade client.rpc junto con el helper client.sendTransaction. Exporta el tipo del cliente envuelto en Awaited<> para que permanezca correcto si más adelante agregas un plugin que se resuelve de forma asíncrona, y pasa ese AppClient a cada llamada useClient.
Envuelve tu árbol una sola vez
ClientProvider publica el cliente. Los hooks de datos (useRequest, useSubscription, useTrackedData) lo leen mediante useClient. Los hooks de billetera que se muestran a continuación necesitan que el mismo cliente se les pase explícitamente como primer argumento.
"use client";import { ClientProvider } from "@solana/react";import { client } from "./client";export function Providers({ children }: { children: React.ReactNode }) {return <ClientProvider client={client}>{children}</ClientProvider>;}
Hooks de billetera
Los hooks de billetera necesitan un cliente con un plugin de billetera instalado (p. ej. walletSigner). Obtenlo con useClient<AppClient>() y pásalo como primer argumento de cada hook — esto mantiene la aplicación completamente tipada de extremo a extremo en lugar de depender de búsquedas por contexto.
useWallets(client)— Billeteras Wallet Standard descubiertas para la cadena del cliente.useWalletStatus(client)—"pending" | "disconnected" | "connecting" | "connected" | "disconnecting" | "reconnecting".useConnectedWallet(client)—{ account, signer, wallet }onull.signeresnullpara billeteras de solo lectura.useConnect(client)/useDisconnect(client)— devuelven unActionResultcuyodispatch(ydispatchAsync) ejecuta la acción y cuyosisRunning,status,data,erroryresetrastrean su resultado.
"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>);}
Enviar una transacción
useClient devuelve el mismo cliente que publicaste. Construye instrucciones con un cliente de programa generado y envíalas a través de 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>);}
Pasar el tipo AppClient exportado a useClient le proporciona al hook el cliente completamente extendido con plugins, de modo que client.rpc y client.sendTransaction estén tipados.
Leer datos
@solana/react incluye hooks que leen a través del cliente:
useRequest(source)— lectura RPC de una sola vez; devuelve{ data, error, status, refresh }.useSubscription(source)— una suscripción en vivo; devuelve{ data, error, reconnect, status }.useTrackedData(spec)— un valor inicializado por RPC que se mantiene actualizado mediante una suscripción.
"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>);}
Memoiza la fuente (con useMemo, o useCallback para una función) para que el hook solo vuelva a obtener datos cuando cambien sus entradas y no en cada render.
Para el caché y la revalidación, las subrutas @solana/react/swr y @solana/react/query envuelven los mismos hooks para SWR y TanStack Query.
Patrones comunes para desarrolladores de Solana
- Un solo proveedor:
ClientProvideres el único proveedor que necesitas; obtén el cliente conuseClient<AppClient>()y pásalo a los hooks de billetera. - Compatible con Server Components: Solo marca con
"use client"los componentes hoja que llamen hooks; las lecturas del servidor pueden usar un cliente RPC de Kit sin billetera. - Testing: Publica un cliente simulado a través de
ClientProviderpara simular billeteras y respuestas RPC.
Dos familias de hooks, mismos nombres
useSignIn y useSignMessage existen tanto en @solana/react (reciben un argumento UiWalletAccount) como en @solana/kit-plugin-wallet/react (reciben el client en su lugar y devuelven un ActionResult). Usa las versiones de @solana/kit-plugin-wallet/react con el patrón de cliente descrito anteriormente; los hooks de billetera más antiguos de @solana/react están siendo reemplazados.
Combina esta guía con la descripción general del cliente Kit para comprender el cliente que lee cada hook.
Is this page helpful?