调用合约时,在哪里加载合约以防止未定义的方法?
Where to load contract to prevent undefined methods when calling contract?
我正在尝试 运行 来自我位于 ropsten 测试网络上的智能合约的方法,但是 运行 我的 getBalance() 函数中出现以下错误:
Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading 'methods')
46 | async function getBalance() {
> 47 | const tempBal = await window.contract.methods.balanceOf(account.data).call()
| ^
48 | setBalance(tempBal)
49 | }
连接我的合约:
export default function ConnectContract() {
async function loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
window.ethereum.enable()
}
}
async function loadContract() {
const tempContract = await new window.web3.eth.Contract(ABI, ContractAddress)
return tempContract
}
async function load() {
await loadWeb3();
window.contract = await loadContract();
}
load();
}
目前调用的函数是这样的:
export default function Page() {
ConnectContract();
getBalance();
}
我之前调用它的另一种不会导致未定义错误的方法是在按钮内使用 onClick 函数来获取平衡:
<div><button onClick={() => getBalance}>Get Balance</button></div>
我知道像这样调用它们会导致在合约连接到网站之前调用 getBalance 函数方法,但使用当前代码,它在刷新 1 页后工作。但是我还没有找到让合约加载的解决方案,所以该方法是在调用 getBalance 时定义的。
我已经尝试执行 onLoad 函数和 window.load() 函数但没有成功。我还尝试在 _app.js 中调用我的 ConnectContract 函数以在网站启动时加载它,但也没有成功。
您必须在 useEffect
钩子中调用 loadWeb3
函数。 useEffect
用于准备组件安装时的状态。要跟踪状态,请使用 useState
hook
const [web3,setWeb3]=useState('')
const [contract,setContract]=useState('')
async function loadWeb3() {
if (window.ethereum) {
window.ethereum.enable()
setWeb3(new Web3(window.ethereum))
}
}
// [] array means we want this useEffect code run only when the compoenent rerenders
// Since loadWeb3 is async function, call it inside try/catch block
useEffect(()=>{loadWeb3()},[])
接下来我们需要按照同样的方式准备合同。
async function loadContract() {
const tempContract = await new web3.eth.Contract(ABI, ContractAddress)
setContract(tempContract)
}
你也需要在useEffect
中调用它,但这次它的依赖关系不同了。因为为了拿到合约,我们靠的是web3
// Since loadContract is async function, call it inside try/catch block
useEffect(()=>{loadContract},[web3])
当组件渲染时,首先 useEffect 将 运行 并设置 web3
。由于 web3 已更改,组件将再次重新呈现此 useEffect 将 运行。因此,当您的组件被安装时,您将设置 web3
和 contract
以便您可以使用它们。
您的问题出在这段代码中:
46 | async function getBalance() {
> 47 | const tempBal = await window.contract.methods.balanceOf(account.data).call()
| ^
48 | setBalance(tempBal)
49 | }
我的猜测是 window.contract 要么不存在,要么在调用它之前没有加载。也许它要么在 window 不存在的服务器端位置被调用,要么尝试将其包装在 if 函数中,以便它在调用它之前检查以确保它存在
我正在尝试 运行 来自我位于 ropsten 测试网络上的智能合约的方法,但是 运行 我的 getBalance() 函数中出现以下错误:
Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'methods')
46 | async function getBalance() {
> 47 | const tempBal = await window.contract.methods.balanceOf(account.data).call()
| ^
48 | setBalance(tempBal)
49 | }
连接我的合约:
export default function ConnectContract() {
async function loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
window.ethereum.enable()
}
}
async function loadContract() {
const tempContract = await new window.web3.eth.Contract(ABI, ContractAddress)
return tempContract
}
async function load() {
await loadWeb3();
window.contract = await loadContract();
}
load();
}
目前调用的函数是这样的:
export default function Page() {
ConnectContract();
getBalance();
}
我之前调用它的另一种不会导致未定义错误的方法是在按钮内使用 onClick 函数来获取平衡:
<div><button onClick={() => getBalance}>Get Balance</button></div>
我知道像这样调用它们会导致在合约连接到网站之前调用 getBalance 函数方法,但使用当前代码,它在刷新 1 页后工作。但是我还没有找到让合约加载的解决方案,所以该方法是在调用 getBalance 时定义的。
我已经尝试执行 onLoad 函数和 window.load() 函数但没有成功。我还尝试在 _app.js 中调用我的 ConnectContract 函数以在网站启动时加载它,但也没有成功。
您必须在 useEffect
钩子中调用 loadWeb3
函数。 useEffect
用于准备组件安装时的状态。要跟踪状态,请使用 useState
hook
const [web3,setWeb3]=useState('')
const [contract,setContract]=useState('')
async function loadWeb3() {
if (window.ethereum) {
window.ethereum.enable()
setWeb3(new Web3(window.ethereum))
}
}
// [] array means we want this useEffect code run only when the compoenent rerenders
// Since loadWeb3 is async function, call it inside try/catch block
useEffect(()=>{loadWeb3()},[])
接下来我们需要按照同样的方式准备合同。
async function loadContract() {
const tempContract = await new web3.eth.Contract(ABI, ContractAddress)
setContract(tempContract)
}
你也需要在useEffect
中调用它,但这次它的依赖关系不同了。因为为了拿到合约,我们靠的是web3
// Since loadContract is async function, call it inside try/catch block
useEffect(()=>{loadContract},[web3])
当组件渲染时,首先 useEffect 将 运行 并设置 web3
。由于 web3 已更改,组件将再次重新呈现此 useEffect 将 运行。因此,当您的组件被安装时,您将设置 web3
和 contract
以便您可以使用它们。
您的问题出在这段代码中:
46 | async function getBalance() {
> 47 | const tempBal = await window.contract.methods.balanceOf(account.data).call()
| ^
48 | setBalance(tempBal)
49 | }
我的猜测是 window.contract 要么不存在,要么在调用它之前没有加载。也许它要么在 window 不存在的服务器端位置被调用,要么尝试将其包装在 if 函数中,以便它在调用它之前检查以确保它存在