You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让React useEffect在智能合约调用后正确显示更新后的变量?

问题根因

你当前的代码存在基础逻辑错误:你把useEffect内部修改的状态变量tetherBalance、amountDeposited加入了依赖数组,这会导致每次状态更新后都会重新触发useEffect执行,形成无限重跑的死循环,反而会干扰正常的状态更新逻辑。同时你没有针对存币交易的完成时机做主动的状态刷新,自然无法拿到链上更新后的最新数据。

可行解决方案

1. 先修正useEffect依赖逻辑

首先把拉取用户数据的逻辑抽成可复用的公共函数,同时移除useEffect中不需要的依赖项,只保留会影响数据拉取逻辑的外部变量:

function App() {
  const [tether, setTether] = React.useState([undefined]);
  const [tetherAddress, setTetherAddress] = React.useState("");
  const [tetherBalance, setTetherBalance] = React.useState("0");
  const [amountDeposited, setAmountDeposited] = React.useState("0");
  window.web3 = new Web3(window.web3.currentProvider);

  // 抽离为公共函数,多处可调用
  const fetchUserData = async (currentAccount) => {
    if (!currentAccount || !tether || !chadsVault) return
    const tetherBalance = await tether.methods.balanceOf(currentAccount).call()
    setTetherBalance(tetherBalance.toString())
    const deposited = await chadsVault.methods.amountDeposited(currentAccount).call()
    setAmountDeposited(deposited.toString())
  }

  useEffect(() => {
    // 只有账户、合约实例变化时才初始化拉取数据
    fetchUserData(account)
  }, [account, tether, chadsVault]) // 只保留外部依赖,不要放内部会修改的状态

2. 存币交易确认后主动触发数据刷新

不需要靠useEffect被动监听变化,在用户发起存币的逻辑中,等待交易上链确认后直接调用fetchUserData即可实现无刷新更新:

const handleDeposit = async (depositAmount) => {
    // 第一步:先授权合约使用ERC20额度(如果需要的话)
    await tether.methods.approve(chadsVaultAddress, depositAmount).send({ from: account })
    // 第二步:调用存币方法,等待交易确认
    const depositTx = await chadsVault.methods.deposit(depositAmount).send({ from: account })
    // 交易被区块确认后,主动拉取最新数据
    if (depositTx.status) {
      await fetchUserData(account)
    }
  }

3. 可选:订阅合约事件实现自动更新

如果想要实现其他地址给当前账户转币、或者其他链上操作触发余额变化时也能自动更新,可以订阅合约的相关事件,收到事件后自动拉取数据:

useEffect(() => {
    if (!account || !tether || !chadsVault) return
    // 订阅ERC20的Transfer事件,筛选接收方为当前账户的交易
    const transferEvent = tether.events.Transfer({
      filter: { to: account },
      fromBlock: 'latest'
    }).on('data', async () => {
      await fetchUserData(account)
    })
    // 订阅质押合约的Deposit事件
    const depositEvent = chadsVault.events.Deposit({
      filter: { user: account },
      fromBlock: 'latest'
    }).on('data', async () => {
      await fetchUserData(account)
    })
    // 组件卸载时取消订阅避免内存泄漏
    return () => {
      transferEvent.unsubscribe()
      depositEvent.unsubscribe()
    }
  }, [account, tether, chadsVault])
}

内容的提问来源于stack exchange,提问作者Bdellinger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:36:04