React

@solana/react публікує Kit-клієнт у дерево компонентів через один провайдер, а хуки зчитують з нього дані RPC, підписки та стан гаманця. Хуки браузерного гаманця знаходяться у @solana/kit-plugin-wallet/react і використовують той самий провайдер — окремий провайдер гаманця не потрібен.

Встановлення

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

Побудова клієнта

Побудуйте клієнт один раз на рівні модуля, за межами дерева React. У браузері walletSigner робить підключений гаманець одночасно платником комісії та ідентифікатором.

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 додає client.wallet (виявлення та підключення за стандартом Wallet Standard), а solanaRpcclient.rpc та допоміжний метод client.sendTransaction. Експортуйте тип клієнта, обгорнутий у Awaited<>, щоб він залишався коректним, якщо пізніше ви додасте плагін, що розв'язується асинхронно, та передайте цей AppClient у кожен виклик useClient.

Огорніть дерево один раз

ClientProvider публікує клієнт. Хуки даних (useRequest, useSubscription, useTrackedData) зчитують його через useClient. Хуки гаманця нижче потребують явної передачі того самого клієнта як першого аргументу.

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>;
}

Хуки гаманця

Хуки гаманця потребують клієнта з встановленим плагіном гаманця (наприклад, walletSigner). Отримайте його через useClient<AppClient>() і передайте як перший аргумент кожного хука — це забезпечує повну типізацію застосунку наскрізь, замість покладання на пошук у контексті.

  • useWallets(client) — гаманці Wallet Standard, виявлені для ланцюга клієнта.
  • useWalletStatus(client)"pending" | "disconnected" | "connecting" | "connected" | "disconnecting" | "reconnecting".
  • useConnectedWallet(client){ account, signer, wallet } або null. signer має значення null для гаманців лише для читання.
  • useConnect(client) / useDisconnect(client) — повертають ActionResult, чий dispatchdispatchAsync) виконує дію, а isRunning, status, data, error та reset відстежують її результат.
"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>
);
}

Надсилання транзакції

useClient повертає той самий клієнт, який ви опублікували. Побудуйте інструкції за допомогою згенерованого клієнта програми та надішліть їх через 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>
);
}

Передача експортованого типу AppClient у useClient надає хуку повний клієнт із розширеними плагінами, завдяки чому client.rpc та client.sendTransaction є типізованими.

Читання даних

@solana/react постачається з хуками, що зчитують дані через клієнт:

  • useRequest(source) — одноразове зчитування RPC; повертає { data, error, status, refresh }.
  • useSubscription(source) — активна підписка; повертає { data, error, reconnect, status }.
  • useTrackedData(spec) — значення, початково отримане через RPC та підтримуване актуальним за допомогою підписки.
"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>
);
}

Мемоізуйте джерело (за допомогою useMemo або useCallback для функції), щоб хук виконував повторний запит лише при зміні вхідних даних, а не при кожному рендері.

Для кешування та ревалідації підшляхи @solana/react/swr і @solana/react/query обгортають ті самі хуки для SWR і TanStack Query.

Типові патерни для розробників Solana

  • Один провайдер: ClientProvider — єдиний провайдер, який вам потрібен; отримайте клієнт через useClient<AppClient>() і передайте його у хуки гаманця.
  • Підтримка серверних компонентів: Позначайте "use client" лише листові компоненти, що викликають хуки; серверні запити можуть використовувати звичайний RPC-клієнт Kit без гаманця.
  • Тестування: Опублікуйте замоканий клієнт через ClientProvider для імітації гаманців і RPC-відповідей.

Дві родини хуків, однакові назви

useSignIn і useSignMessage існують як у @solana/react (приймають аргумент UiWalletAccount), так і в @solana/kit-plugin-wallet/react (приймають client, повертають ActionResult). Використовуйте версії з @solana/kit-plugin-wallet/react з патерном клієнта, описаним вище; старіші хуки гаманця з @solana/react поступово виводяться з використання.

Поєднайте цей посібник з оглядом Kit-клієнта, щоб зрозуміти клієнт, з якого зчитує кожен хук.

Is this page helpful?