React

@solana/react ينشر عميل Kit إلى شجرة المكوّنات من خلال موفّر واحد، ثم تقرأ الـ hooks بيانات RPC والاشتراكات وحالة المحفظة منه. تعيش hooks محفظة المتصفح في @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 العميل. تقرأ hooks البيانات (useRequest وuseSubscription وuseTrackedData) منه عبر useClient. تحتاج hooks المحفظة أدناه إلى تمرير نفس العميل صراحةً كأول وسيط لها.

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

Hooks المحفظة

تحتاج hooks المحفظة إلى عميل مثبَّت عليه مكوّن إضافي للمحفظة (مثل walletSigner). احصل عليه من useClient<AppClient>() ومرّره كأول وسيط لكل hook — هذا يُبقي التطبيق مكتمل الأنواع من البداية إلى النهاية بدلاً من الاعتماد على عمليات بحث السياق.

  • 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 يمنح الـ hook العميل الكامل الممتد بالمكوّنات الإضافية، بحيث يكون client.rpc وclient.sendTransaction محدَّدَي النوع.

قراءة البيانات

تشحن @solana/react hooks تقرأ عبر العميل:

  • 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 للدوال) حتى لا يُعيد الـ hook الجلب إلا عند تغيّر مدخلاته، لا عند كل إعادة تصيير.

للتخزين المؤقت وإعادة التحقق، تُغلّف المسارات الفرعية @solana/react/swr و@solana/react/query نفس الـ hooks لاستخدامها مع SWR وTanStack Query.

أنماط شائعة لمطوّري سولانا

  • موفّر واحد: ClientProvider هو الموفّر الوحيد الذي تحتاجه؛ احصل على العميل بـ useClient<AppClient>() ومرّره إلى hooks المحفظة.
  • متوافق مع مكوّنات الخادم: ضع "use client" فقط على مكوّنات الأوراق التي تستدعي الـ hooks؛ يمكن لقراءات الخادم استخدام عميل Kit RPC عادي بدون محفظة.
  • الاختبار: انشر عميلاً وهمياً عبر ClientProvider لمحاكاة المحافظ واستجابات RPC.

عائلتا hook، نفس الأسماء

useSignIn وuseSignMessage موجودتان في كلٍّ من @solana/react (تأخذان وسيط UiWalletAccount) و@solana/kit-plugin-wallet/react (تأخذان client بدلاً منه، وتُعيدان ActionResult). استخدم إصدارَي @solana/kit-plugin-wallet/react مع نمط العميل أعلاه؛ hooks المحفظة القديمة في @solana/react يجري استبدالها.

اقرن هذا الدليل بـ نظرة عامة على عميل Kit لفهم العميل الذي تقرأ منه كل hook.

Is this page helpful?

جدول المحتويات

تعديل الصفحة