如何将Solidity的addParticipant函数接入React?Context.jsx代码咨询
问题
需要将以下Solidity合约中的添加参与者功能接入React项目,请问在Context.jsx文件中应编写何种正确代码?
对应的Solidity合约代码
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; contract Transactions{ uint32 public participant_id = 0; // 参与者ID struct participant { string userName; string password; string participantType; address participantAddress; // 以太坊账户地址 } mapping(uint32 => participant) public participants; // 参与者列表 // addParticipant函数用于添加带有不同属性的新参与者 function addParticipant(string memory _name, string memory _pass, address _pAdd, string memory _pType) public returns (uint32) { uint32 userId = participant_id++;// 自增参与者ID participants[userId].userName = _name; participants[userId].password = _pass; participants[userId].participantAddress = _pAdd; participants[userId].participantType = _pType; return userId; } }
解决方案
在React的Context.jsx中,我们结合ethers.js实现合约交互,同时管理钱包连接状态和添加参与者的核心逻辑,以下是完整代码:
import { createContext, useContext, useState, useEffect } from 'react'; import { ethers } from 'ethers'; // 导入合约ABI,建议单独存放在abi.json文件中 import TransactionsABI from './abi.json'; const AppContext = createContext(); // 替换为你的合约部署地址 const CONTRACT_ADDRESS = "0xYourContractAddressHere"; export const AppProvider = ({ children }) => { const [provider, setProvider] = useState(null); const [signer, setSigner] = useState(null); const [contract, setContract] = useState(null); const [isConnected, setIsConnected] = useState(false); // 初始化钱包连接与合约实例 useEffect(() => { const initContract = async () => { if (!window.ethereum) { alert("请安装MetaMask等以太坊钱包"); return; } const tempProvider = new ethers.BrowserProvider(window.ethereum); setProvider(tempProvider); // 监听账户切换,自动刷新状态 window.ethereum.on('accountsChanged', () => window.location.reload()); try { const tempSigner = await tempProvider.getSigner(); const tempContract = new ethers.Contract(CONTRACT_ADDRESS, TransactionsABI, tempSigner); setSigner(tempSigner); setContract(tempContract); setIsConnected(true); } catch (err) { console.error("合约初始化失败:", err); } }; initContract(); }, []); // 添加参与者的核心函数 const addParticipant = async (name, password, participantAddress, participantType) => { if (!contract) { alert("请先连接钱包"); return false; } try { // 调用合约方法并发起交易 const tx = await contract.addParticipant(name, password, participantAddress, participantType); // 等待交易上链确认 await tx.wait(); console.log("参与者添加成功,交易哈希:", tx.hash); return true; } catch (err) { console.error("添加参与者失败:", err); alert("添加失败,请检查参数或钱包权限"); return false; } }; return ( <AppContext.Provider value={{ isConnected, addParticipant }}> {children} </AppContext.Provider> ); }; // 自定义Hook,方便组件调用Context内容 export const useAppContext = () => useContext(AppContext);
关键说明
- ABI文件:需将Solidity合约编译后的ABI导出为
abi.json,确保文件路径正确。 - 合约地址:必须替换
CONTRACT_ADDRESS为实际部署的合约地址。 - 钱包兼容:代码默认适配MetaMask,若使用其他钱包需调整连接逻辑。
- 组件调用示例:在业务组件中通过
useAppContextHook调用addParticipant函数即可完成交互:
import { useAppContext } from './Context'; const AddParticipantForm = () => { const { addParticipant } = useAppContext(); const handleSubmit = async (e) => { e.preventDefault(); const name = e.target.name.value; const password = e.target.password.value; const address = e.target.address.value; const type = e.target.type.value; await addParticipant(name, password, address, type); }; return ( <form onSubmit={handleSubmit}> <input name="name" placeholder="用户名" /> <input name="password" placeholder="密码" /> <input name="address" placeholder="以太坊地址" /> <input name="type" placeholder="参与者类型" /> <button type="submit">添加参与者</button> </form> ); };
内容的提问来源于stack exchange,提问作者Marco Marco
相关产品推荐
相关产品推荐

