React

@solana/react xuất bản một Kit client vào cây component của bạn thông qua một provider duy nhất, sau đó các hook đọc dữ liệu RPC, subscription và trạng thái ví từ đó. Các hook ví cho trình duyệt nằm trong @solana/kit-plugin-wallet/react và đọc cùng một provider — không cần provider ví riêng biệt.

Cài đặt

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

Xây dựng client

Xây dựng client một lần, ở phạm vi module, bên ngoài cây React. Trên trình duyệt, walletSigner biến ví đã kết nối thành cả người trả phí lẫn danh tính.

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 thêm client.wallet (khám phá và kết nối theo Wallet Standard), và solanaRpc thêm client.rpc cùng helper client.sendTransaction. Xuất kiểu client được bọc trong Awaited<> để kiểu vẫn chính xác nếu sau này bạn thêm một plugin phân giải bất đồng bộ, và truyền AppClient đó vào mọi lời gọi useClient.

Bọc cây component một lần

ClientProvider xuất bản client. Các hook dữ liệu (useRequest, useSubscription, useTrackedData) đọc client đó qua useClient. Các hook ví phía dưới cần được truyền cùng một client một cách tường minh làm đối số đầu tiên.

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

Hook ví

Các hook ví cần một client có cài đặt wallet plugin (ví dụ: walletSigner). Lấy nó từ useClient<AppClient>() và truyền làm đối số đầu tiên của mỗi hook — cách này giúp ứng dụng được định kiểu đầy đủ từ đầu đến cuối thay vì dựa vào tra cứu context.

  • useWallets(client) — Các ví theo Wallet Standard được khám phá cho chain của client.
  • useWalletStatus(client)"pending" | "disconnected" | "connecting" | "connected" | "disconnecting" | "reconnecting".
  • useConnectedWallet(client){ account, signer, wallet } hoặc null. signernull đối với ví chỉ đọc.
  • useConnect(client) / useDisconnect(client) — trả về một ActionResultdispatch (và dispatchAsync) thực thi hành động, và isRunning, status, data, error, cùng reset theo dõi kết quả của nó.
"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>
);
}

Gửi giao dịch

useClient trả về cùng một client bạn đã xuất bản. Xây dựng các instruction bằng client chương trình được tạo tự động và gửi chúng qua 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>
);
}

Truyền kiểu AppClient đã xuất vào useClient sẽ cung cấp cho hook client đầy đủ với các plugin mở rộng, nhờ đó client.rpcclient.sendTransaction được định kiểu chính xác.

Đọc dữ liệu

@solana/react cung cấp các hook đọc dữ liệu qua client:

  • useRequest(source) — đọc RPC một lần; trả về { data, error, status, refresh }.
  • useSubscription(source) — subscription trực tiếp; trả về { data, error, reconnect, status }.
  • useTrackedData(spec) — một giá trị được khởi tạo từ RPC và được giữ mới bởi subscription.
"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>
);
}

Ghi nhớ (memoize) source (dùng useMemo, hoặc useCallback cho hàm) để hook chỉ tải lại khi đầu vào thay đổi thay vì mỗi lần render.

Để caching và revalidation, các subpath @solana/react/swr@solana/react/query bọc cùng các hook đó cho SWRTanStack Query.

Các pattern phổ biến cho dev Solana

  • Một provider duy nhất: ClientProvider là provider duy nhất bạn cần; lấy client bằng useClient<AppClient>() và truyền vào các hook ví.
  • Hỗ trợ Server Component: Chỉ đánh dấu "use client" cho các leaf component gọi hook; các tác vụ đọc phía server có thể dùng Kit RPC client thuần túy không cần ví.
  • Testing: Xuất bản một client giả lập qua ClientProvider để mô phỏng ví và các phản hồi RPC.

Hai họ hook, cùng tên

useSignInuseSignMessage tồn tại trong cả @solana/react (nhận đối số UiWalletAccount) và @solana/kit-plugin-wallet/react (nhận client thay thế, trả về ActionResult). Hãy dùng các phiên bản @solana/kit-plugin-wallet/react theo pattern client ở trên; các hook ví @solana/react cũ đang dần bị thay thế.

Kết hợp hướng dẫn này với tổng quan Kit client để hiểu rõ client mà mỗi hook đọc từ đó.

Is this page helpful?

Mục lục

Chỉnh sửa trang