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

Next.js中Web3区块链数据获取后useState状态未更新求助

问题解析与修复方案

核心问题拆解

  1. 变量重名混淆:你在getInventoryHandler里声明了和状态变量同名的局部inventory,虽然语法合法,但会让你误以为打印的是状态值,其实是区块链返回的局部数据;同时这种命名方式也容易引发逻辑混淆。
  2. useEffect依赖错误导致无限循环:把inventory放进useEffect依赖数组后,每次setInventory更新状态都会触发useEffect重新执行,进而再次调用getInventoryHandler更新状态,形成无限循环——这也是你看到多次空输出的核心原因。
  3. 初始渲染空值:组件挂载时inventory初始值为空字符串,异步请求完成前组件已经完成第一次渲染,所以会先出现空值输出。

修复后的代码

import { useState, useEffect } from 'react';

// 假设vmContract已正确初始化(比如通过web3实例获取)
export default function InventoryComponent() {
  const [inventory, setInventory] = useState('');
  const [error, setError] = useState(''); // 补上你用到但未声明的error状态

  useEffect(() => {
    // 把请求函数放到useEffect内部,避免外部依赖问题
    const fetchInventory = async () => {
      try {
        // 调用区块链合约方法获取数据
        const fetchedData = await vmContract.methods.getVendingBalance().call();
        // 用不同变量名区分局部数据和状态,避免混淆
        setInventory(fetchedData);
        console.log('获取到的库存数据:', fetchedData);
      } catch (err) {
        setError(err.message);
        console.error('数据获取失败:', err);
      }
    };

    // 组件挂载时执行一次请求
    fetchInventory();
  }, []); // 空依赖数组:仅在组件首次挂载时执行

  return (
    <div>
      <p>当前库存:{inventory || '加载中...'}</p>
      {error && <p style={{ color: 'red' }}>错误:{error}</p>}
    </div>
  );
}

可选:定时刷新数据

如果需要实时同步区块链数据,可以添加定时器定期刷新,记得在组件卸载时清除定时器避免内存泄漏:

useEffect(() => {
  const fetchInventory = async () => {
    try {
      const fetchedData = await vmContract.methods.getVendingBalance().call();
      setInventory(fetchedData);
    } catch (err) {
      setError(err.message);
    }
  };

  // 立即执行一次
  fetchInventory();
  // 每5秒刷新一次数据
  const refreshInterval = setInterval(fetchInventory, 5000);

  // 组件卸载时清除定时器
  return () => clearInterval(refreshInterval);
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:41:19