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), а solanaRpc добавляет client.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" только конечные компоненты, вызывающие хуки; серверные чтения могут использовать обычный Kit RPC-клиент без кошелька.
  • Тестирование: публикуйте замоканный клиент через 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?

Содержание

Редактировать страницу