@web3-react/core 是一个专为 React 设计的钱包连接状态管理库,它通过 Hooks 和 Context 简化了用户钱包连接、切换网络和维护会话状态的流程。ethers 则是一个完整的以太坊协议交互库,提供了签名、交易发送、合约读写等底层能力,不依赖特定前端框架。两者通常配合使用:@web3-react/core 管理 UI 状态,ethers 负责实际的链上操作。
在构建以太坊去中心化应用(dApp)时,开发者常面临一个架构问题:如何管理钱包连接状态,以及如何与区块链交互。@web3-react/core 和 ethers 分别解决了这两个不同层面的问题。前者专注于 React 应用中的连接状态管理,后者专注于以太坊协议本身的交互能力。让我们从实际工程角度对比它们的工作方式。
@web3-react/core 将钱包连接抽象为 React Hooks。
window.ethereum 注入。connector.activate() 触发连接,状态自动更新。// @web3-react/core: 使用 Hook 管理连接
import { useWeb3React } from '@web3-react/core';
function ConnectButton() {
const { account, activate, connector } = useWeb3React();
const handleConnect = async () => {
try {
await activate(connector); // 触发连接
} catch (error) {
console.error(error);
}
};
return <button onClick={handleConnect}>连接钱包</button>;
}
ethers 需要手动获取 Provider。
window.ethereum。// ethers: 手动创建 Provider
import { BrowserProvider } from 'ethers';
async function connectWallet() {
if (window.ethereum) {
const provider = new BrowserProvider(window.ethereum);
await provider.send('eth_requestAccounts', []); // 请求访问
const signer = await provider.getSigner();
const address = await signer.getAddress();
console.log('Connected:', address);
}
}
@web3-react/core 内置了状态管理。
useState 和 useEffect 的样板代码。// @web3-react/core: 自动响应状态变化
function AccountDisplay() {
const { account, chainId, isActive } = useWeb3React();
if (!isActive) return <div>未连接</div>;
return <div>{account} - Chain: {chainId}</div>; // 自动更新
}
ethers 是无状态的工具库。
provider.on('accountsChanged')。// ethers: 手动监听状态变化
import { useEffect, useState } from 'react';
import { BrowserProvider } from 'ethers';
function AccountDisplay() {
const [account, setAccount] = useState(null);
useEffect(() => {
if (window.ethereum) {
const provider = new BrowserProvider(window.ethereum);
provider.on('accountsChanged', (accounts) => {
setAccount(accounts[0]); // 手动更新状态
});
}
}, []);
return <div>{account || '未连接'}</div>;
}
@web3-react/core 不直接处理合约。
provider 对象给其他库使用。ethers 或 viem 一起完成合约调用。// @web3-react/core: 获取 Provider 供外部使用
import { useWeb3React } from '@web3-react/core';
import { Contract } from 'ethers';
function ReadContract() {
const { provider } = useWeb3React();
const readData = async () => {
if (provider) {
const contract = new Contract(address, abi, provider);
const value = await contract.readMethod();
console.log(value);
}
};
// ...
}
ethers 核心功能就是合约交互。
Contract 类来封装 ABI 和地址。// ethers: 实例化并调用合约
import { Contract, BrowserProvider } from 'ethers';
async function callContract() {
const provider = new BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const contract = new Contract(address, abi, signer);
const tx = await contract.writeMethod(arg); // 发送交易
await tx.wait(); // 等待确认
}
@web3-react/core 通过 Hook 参数简化多链。
activate 时指定链 ID。chainId 供 UI 判断。// @web3-react/core: 切换网络
import { useWeb3React } from '@web3-react/core';
function NetworkSwitcher() {
const { activate, connector } = useWeb3React();
const switchToPolygon = () => {
// 部分连接器支持直接切换链
activate(connector, undefined, 137); // 137 是 Polygon 链 ID
};
// ...
}
ethers 需要手动切换 Provider 实例。
// ethers: 手动切换 RPC Provider
import { JsonRpcProvider } from 'ethers';
function switchNetwork(chainId) {
const rpcUrl = getRpcUrl(chainId); // 自定义配置
const provider = new JsonRpcProvider(rpcUrl);
// 需要手动更新应用中的 provider 实例
return provider;
}
虽然职责不同,但它们在现代 dApp 架构中紧密合作。以下是关键的重叠与协作点:
// 共同模式:异步等待
// web3-react
await activate(connector);
// ethers
await provider.send('eth_requestAccounts', []);
// 共同模式:请求签名
// web3-react (通过 provider)
const signature = await provider.send('personal_sign', [msg, account]);
// ethers
const signature = await signer.signMessage(msg);
// 共同模式:Try/Catch
try {
// 操作...
} catch (err) {
if (err.code === 4001) console.log('用户拒绝');
}
| 特性 | @web3-react/core | ethers |
|---|---|---|
| 核心职责 | 🎨 React 状态管理 | ⚙️ 协议交互引擎 |
| 框架依赖 | ⚛️ 必须 React | 🌐 任意 JS 环境 |
| 钱包连接 | ✅ 内置 Hooks 封装 | ❌ 需手动实现 |
| 合约调用 | ❌ 需配合其他库 | ✅ 内置 Contract 类 |
| 状态同步 | ✅ 自动响应式 | ❌ 手动监听事件 |
| 典型场景 | 连接按钮、账户显示 | 交易发送、合约读写 |
@web3-react/core 就像是一个专门的管理员 🧑💼,负责维护用户连接状态、处理钱包弹窗和切换网络,让 React 组件能轻松获取当前账户信息。适合用于构建 dApp 的导航栏、连接按钮和用户状态展示。
ethers 就像是一个工程师 🔧,负责实际干活,比如构造交易数据、签名、发送请求到节点并解析返回结果。它是业务逻辑的核心,无论是否使用 React 都不可或缺。
最佳实践:在 React 项目中,通常同时使用两者。用 @web3-react/core 管理连接状态,获取 provider 后传入 ethers 进行实际交互。不要试图用 ethers 手写所有连接逻辑,也不要指望 @web3-react/core 能直接发送交易。各司其职,代码更清晰。
如果你的项目基于 React 且需要标准化的钱包连接流程,选择 @web3-react/core。它封装了复杂的连接器逻辑,提供了 useWeb3React 等 Hooks,让你无需手动管理 provider 注入和状态同步,适合快速构建 dApp 前端界面。
如果你需要直接与以太坊区块链交互,如签名消息、发送交易或读取合约数据,必须选择 ethers。它是底层协议库,无论是否使用 React 都需要它(或类似库如 viem),适合处理核心的业务逻辑和链上数据操作。