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

React新手求助:如何稳定渲染区块链与IPFS的动态表格数据?

问题诊断与修复方案

核心问题

你的代码存在两个关键问题导致数据渲染不稳定:

  • applicationNumberArray.map(async ...) 中的异步函数不会被等待,listOfApplication 经常在所有请求完成前就被传入setDataTable;硬编码的setTimeout(3000)完全依赖网络运气,网络延迟高时数据还没返回就更新了状态。
  • 使用全局变量applicationContract、metamaskAddress、applicationNumberArray,组件重渲染时容易引发竞态,导致数据混乱。

修复后的完整代码

import { useState, useEffect } from "react";
import { useLoaderData } from "react-router-dom";
import Table from "../components/Table";
import { Buffer } from 'buffer';
import getHashFromIPFS from "../services/getHashFromIPFS";

function ViewApplication() {
  const { fetchBlockchainData } = useLoaderData();
  const [dataTable, setDataTable] = useState([]);
  const [isLoading, setIsLoading] = useState(true); // 新增加载状态
  // 变量移至组件内部,避免全局竞态
  const metamaskAddress = fetchBlockchainData[0];
  const applicationContract = fetchBlockchainData[2];

  useEffect(() => {
    const fetchData = async () => {
      try {
        // Step 1: 获取用户的申请编号列表
        const applicationNumberArray = await applicationContract.methods.getUserApplication(metamaskAddress).call();
        
        // Step 2: 用Promise.all等待所有详情请求完成
        const listOfApplication = await Promise.all(
          applicationNumberArray.map(async (appno) => getApplicationDetails(appno))
        );
        
        // Step 3: 所有数据就绪后再更新状态
        setDataTable(listOfApplication);
      } catch (err) {
        console.error('数据获取失败:', err);
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, [metamaskAddress, applicationContract]); // 添加依赖项,符合hooks规则

  // 优化异步函数写法,消除嵌套then
  const getApplicationDetails = async (appno) => {
    const AppDataHash = await applicationContract.methods.getApplicationData(appno).call();
    const getData = await getHashFromIPFS(AppDataHash);
    return JSON.parse(Buffer.from(getData.value.buffer).toString());
  };

  // 加载状态提示
  if (isLoading) {
    return <div>加载中...</div>;
  }

  // 空数据提示
  if (dataTable.length === 0) {
    return <div>暂无申请记录</div>;
  }

  // 表格配置
  const config = [
    { label: 'Application No.', render: (data) => data.applicationno },
    { label: 'Name', render: (data) => data.name },
    { label: 'Status', render: (data) => data.status },
    { label: '', render: (data) => <>View More</> }
  ];

  const keyFn = (data) => data.applicationno;

  return <Table data={dataTable} config={config} keyFn={keyFn} />;
}

export default ViewApplication;

关键修改说明

  1. 用Promise.all替代map+setTimeout:确保所有IPFS数据请求完成后再一次性更新状态,彻底解决数据缺失问题。
  2. 移除全局变量:将变量移至组件内部,避免组件重渲染时的全局状态污染。
  3. 优化异步逻辑:把getApplicationDetails改成纯async/await形式,消除嵌套then,代码更易读且便于调试。
  4. 添加状态提示:新增加载状态和空数据提示,避免页面空白,提升用户体验。
  5. 完善依赖数组:给useEffect添加正确的依赖项,符合React Hooks规则,避免无效渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:45:19