@solana/react veröffentlicht einen Kit-Client über einen einzigen Provider im Komponentenbaum. Hooks lesen RPC-Daten, Subscriptions und den Wallet-Status daraus. Die Browser-Wallet-Hooks befinden sich in @solana/kit-plugin-wallet/react und lesen denselben Provider – ein separater Wallet-Provider ist nicht erforderlich.
Installation
$npm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-wallet @solana/react
Client erstellen
Erstellen Sie den Client einmalig auf Modulebene, außerhalb des React-Baums. Im Browser macht walletSigner die verbundene Wallet sowohl zum Fee-Zahler als auch zur Identität.
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 fügt client.wallet hinzu (Wallet Standard-Erkennung und -Verbindung), und solanaRpc fügt client.rpc sowie den Hilfs-Helper client.sendTransaction hinzu. Exportieren Sie den Client-Typ in Awaited<> eingebettet, damit er korrekt bleibt, wenn Sie später ein Plugin hinzufügen, das asynchron auflöst, und übergeben Sie diesen AppClient an jeden useClient-Aufruf.
Den Baum einmalig umschließen
ClientProvider veröffentlicht den Client. Die Daten-Hooks (useRequest, useSubscription, useTrackedData) lesen ihn über useClient. Die unten aufgeführten Wallet-Hooks benötigen denselben Client explizit als erstes Argument.
"use client";import { ClientProvider } from "@solana/react";import { client } from "./client";export function Providers({ children }: { children: React.ReactNode }) {return <ClientProvider client={client}>{children}</ClientProvider>;}
Wallet-Hooks
Die Wallet-Hooks benötigen einen Client mit installiertem Wallet-Plugin (z. B. walletSigner). Holen Sie ihn über useClient<AppClient>() und übergeben Sie ihn als erstes Argument jedes Hooks – so bleibt die App vollständig typisiert von Anfang bis Ende, anstatt auf Context-Lookups angewiesen zu sein.
useWallets(client)— Über den Wallet Standard erkannte Wallets für die Chain des Clients.useWalletStatus(client)—"pending" | "disconnected" | "connecting" | "connected" | "disconnecting" | "reconnecting".useConnectedWallet(client)—{ account, signer, wallet }odernull.signeristnullbei schreibgeschützten Wallets.useConnect(client)/useDisconnect(client)— geben einActionResultzurück, dessendispatch(unddispatchAsync) die Aktion ausführt und dessenisRunning,status,data,errorundresetdas Ergebnis verfolgen.
"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>);}
Eine Transaktion senden
useClient gibt denselben Client zurück, den Sie veröffentlicht haben. Erstellen Sie Anweisungen mit einem generierten Programm-Client und senden Sie sie über 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>);}
Durch Übergabe des exportierten AppClient-Typs an useClient erhält der Hook den vollständig plugin-erweiterten Client, sodass client.rpc und client.sendTransaction typisiert sind.
Daten lesen
@solana/react stellt Hooks bereit, die Daten über den Client lesen:
useRequest(source)— Einmaliger RPC-Lesevorgang; gibt{ data, error, status, refresh }zurück.useSubscription(source)— Eine Live-Subscription; gibt{ data, error, reconnect, status }zurück.useTrackedData(spec)— Ein per RPC initialisierter Wert, der durch eine Subscription aktuell gehalten wird.
"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>);}
Memoisieren Sie die Quelle (mit useMemo oder useCallback für eine Funktion), damit der Hook nur bei Änderung seiner Eingaben neu abruft und nicht bei jedem Render.
Für Caching und Revalidierung umschließen die Subpfade @solana/react/swr und @solana/react/query dieselben Hooks für SWR und
TanStack Query.
Gängige Muster für Solana-Entwickler
- Ein Provider:
ClientProviderist der einzige Provider, den Sie benötigen; holen Sie den Client mituseClient<AppClient>()und übergeben Sie ihn an die Wallet-Hooks. - Server-Komponenten-kompatibel: Markieren Sie nur Blatt-Komponenten, die Hooks aufrufen, mit
"use client"; Server-Lesevorgänge können einen einfachen Kit-RPC-Client ohne Wallet verwenden. - Testing: Veröffentlichen Sie einen gemockten Client über
ClientProvider, um Wallets und RPC-Antworten zu simulieren.
Zwei Hook-Familien, gleiche Namen
useSignIn und useSignMessage existieren sowohl in @solana/react (sie nehmen ein UiWalletAccount-Argument) als auch in @solana/kit-plugin-wallet/react (nehmen stattdessen den client und geben ein ActionResult zurück). Verwenden Sie die Versionen aus @solana/kit-plugin-wallet/react mit dem oben beschriebenen Client-Muster; die älteren @solana/react-Wallet-Hooks werden abgelöst.
Ergänzen Sie diesen Leitfaden mit der Kit-Client-Übersicht, um zu verstehen, welchen Client jeder Hook liest.
Is this page helpful?