Implementasi connect wallet yang lengkap: useConnect dan useAccount, injected provider MetaMask dan WalletConnect QR, switch dan deteksi network, serta pola disconnect dan reconnect untuk UX yang mulus

Setelah di episode 9 fondasi DApp berdiri, pada episode ini kita membuat pengalaman pertama user: connect wallet. Ini bukan sekadar tombol — connect wallet adalah "login" DApp, dan kualitasnya menentukan kesan pertama.
Mengapa episode ini penting? Karena connect wallet yang ditangani asal-asalan menghasilkan error yang membingungkan: "salah network", "wallet tidak ditemukan", atau "cannot read properties of undefined". Kita akan membangun versi yang menangani semua kasus itu secara eksplisit — pola yang sama dipakai produksi.
Dua hook yang selalu muncul bersamaan:
useConnect — daftar connector yang tersedia dan aksi untuk connect.useAccount — state akun yang sedang aktif (address, chainId, status).import { useConnect, useAccount } from "wagmi"
export function ConnectButton() {
const { connect, connectors, isPending } = useConnect()
const { address, isConnected } = useAccount()
if (isConnected && address) {
return (
<div>
<span>{address.slice(0, 6)}...{address.slice(-4)}</span>
</div>
)
}
return (
<div>
{connectors.map((connector) => (
<button key={connector.uid} onClick={() => connect({ connector })}>
{isPending ? "Connecting..." : `Connect ${connector.name}`}
</button>
))}
</div>
)
}Perhatikan connector.uid sebagai key — connector adalah array dinamis dari wagmi, dan uid lebih stabil daripada name.
Connector injected mendeteksi wallet yang disuntikkan ke browser — MetaMask, Rabby, Coinbase Wallet, dan lainnya. Ketika user belum menginstall wallet, connector ini tetap muncul tetapi connect akan gagal dengan error Wallet not found.
Handling yang benar:
try {
await connect({ connector })
} catch (err) {
if (err?.message?.includes("not found")) {
setShowInstall(true) // tampilkan tombol install MetaMask
}
}Banyak DApp production memakai @rainbow-me/rainbowkit atau reown (WalletConnect) di atas wagmi untuk UI wallet yang sudah jadi. Untuk series ini kita memahami lapisan dasarnya dulu.
Untuk mobile wallet, pola WalletConnect menampilkan QR yang dipindai wallet. Connector WalletConnect butuh Project ID dari cloud.walletconnect.com:
import { injected, walletConnect } from "wagmi/connectors"
export const wagmiConfig = createConfig({
connectors: [
injected(),
walletConnect({ projectId: import.meta.env.VITE_WC_PROJECT_ID }),
],
// ...chains & transports
})Saat user memilih "Wallet Connect", wagmi menampilkan modal QR — user memindainya dengan wallet mobile, dan sesi tersinkron. Ini jalan utama menuju pengguna mobile.
DApp kalian berjalan di beberapa chain; user mungkin berada di chain yang salah. Dua hook yang dibutuhkan:
import { useAccount, useSwitchChain } from "wagmi"
const { chain } = useAccount()
const { switchChain } = useSwitchChain()
if (chain && chain.id !== targetChainId) {
// tampilkan banner: "Kalian di chain yang salah"
switchChain({ chainId: targetChainId })
}Pattern yang baik:
useAccount().chain.import { useDisconnect } from "wagmi"
const { disconnect } = useDisconnect()User tidak ingin connect ulang setiap membuka halaman. wagmi menyimpan sesi terakhir secara otomatis dan melakukan reconnect saat halaman dimuat — selama connector didaftarkan, sesi akan pulih tanpa interaksi. Pastikan tidak ada logika "wajib klik connect" di awal; useAccount akan memberi tahu ketika status berubah dari reconnecting ke connected.
Tip
Pola UI yang disukai user: tampilkan tombol "Connect Wallet" hanya saat !isConnected; jika isReconnecting, tampilkan spinner; jika isConnected, tampilkan avatar address + menu (disconnect/switch). Status dari useAccount sudah mencakup ketiganya — gunakan sebagai single source of truth.
Rangkuman yang sudah kalian pelajari di episode 10:
useConnect + useAccount adalah pasangan inti; tampilkan connector dari connectors.Inti yang harus dibawa pulang:
useAccount sebagai source of truth UI.Di episode 11 selanjutnya, kita masuk ke jantung interaksi: interaksi contract: read & write — useReadContract untuk membaca state tanpa gas, useWriteContract untuk mengirim transaksi, useWaitForTransactionReceipt untuk memantau konfirmasi, serta pola approve-then-swap dan estimasi gas. Sampai jumpa di episode 11!