reactjs 如何在react table组件上呈现动态数据(来自区块链和IPFS)?

zd287kbt  于 2023-04-05  发布在  React
关注(0)|答案(1)|浏览(110)

前端:React(Beginner in react)后端:区块链、IPFS、Node js
使用IPFS存储应用程序的详细信息(大数据),并将其哈希值保存在用户的区块链(智能合约)中,用户的应用程序编号列表存储在区块链中的数组中。
在react中使用数组从后端(来自区块链和IPFS)渲染应用程序详细信息,但在渲染动态数据时存在问题。在react中显示在表组件上时丢失了一些数据,或者在重新加载页面几次后完整的数据被提取并显示在表组件上。使用多个函数来提取数据。
在表上查看的动态数据,但在表组件上查看的数据或多或少显示在重新加载页面上。

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

import getHashFromIPFS from "../services/getHashFromIPFS";

let applicationContract, metamaskAddress;
let applicationNumberArray;
function ViewApplication() {//Functional Component
  const { fetchBlockchainData } = useLoaderData();  //Fetch metamask wallet and contracts
  const [dataTable, setDataTable] = useState([]); //array to set dynamic data 
  metamaskAddress = fetchBlockchainData[0];
  applicationContract = fetchBlockchainData[2];

  useEffect(() => {
    fetchData() // Function 1
      .then((res) => {
        console.log('res')
        console.log(res)
      })
      .catch(err => console.log(err))
  }, [])

  const fetchData = async () => {
    let appArray = []
    let listOfApplication = []
    // Step 1 : Fetch list of application(application number) of a user from Blockchain 
    applicationNumberArray = await applicationContract.methods.getUserApplication(metamaskAddress).call();
    // Step 2 : Fetch application details(ipfs hash) for each application number
    applicationNumberArray.map(async (applicationNumber) => {
      await getApplicationDetails(applicationNumber) // Function 2
        .then((result) => {
          //tried to set data here but react component re-render in loop
          // setDataTable(result) 
          listOfApplication.push(result)
        })
    })
    setTimeout(() => {
      //Step 5: Set state variable each time data returned
      setDataTable(listOfApplication)
    }, 3000)
  }
    const getApplicationDetails = (appno) => {
      return new Promise(async (res, rej) => {
        //Step 3 : Get Ipfs hash for each application from Blockchain
        await applicationContract.methods.getApplicationData(appno).call().then(async (AppDataHash) => {
          //Step 4 : Extract ipfs hash and return its data 
          await getHashFromIPFS(AppDataHash).then((getData) => {
            let ipfsConverted = JSON.parse(Buffer.from(getData.value.buffer).toString());
            let application = [];
            application = ipfsConverted;
            res(application);
          });
        });
      });

    }
    //Step 6 Set dynamic data to reusable table component 
    let data = dataTable;
    if (data.length > 0) {
      const config = [
        { label: 'Application No.', render: (data) => data.applicationno },
        { label: 'Name', render: (data) => data.name, },
        { label: 'Status', render: (data) => data.status, },
        { label: '', render: (data) => <><button>View More</button></> }
      ];
      const keyFn = (data) => {
        return data.applicationno;
      };
      return (
        <>
          <Table data={data} config={config} keyFn={keyFn} />
        </>
      )
    }
  }
kb5ga3dv

kb5ga3dv1#

你不会等待所有的承诺都完成。
您可以通过将数据获取提升到组件本身之外来简化代码(并像您应该的那样使用async/await而不是new Promise反模式):

async function getApplicationDetails(applicationContract, appno) {
  const appDataHash = await applicationContract.methods.getApplicationData(appno).call();
  const ipfsData = await getHashFromIPFS(appDataHash);
  return JSON.parse(Buffer.from(ipfsData.value.buffer).toString());
}

async function getApplicationsData(applicationContract, metamaskAddress) {
  const applicationNumberArray = await applicationContract.methods.getUserApplication(metamaskAddress).call();
  // Fires off the promises...
  const applicationPromises = applicationNumberArray.map((appNo) => getApplicationDetails(applicationContract, appNo));
  // ... waits for them to finish and gathers the data.
  return await Promise.all(applicationPromises);
}

function ViewApplication() {
  const { fetchBlockchainData } = useLoaderData();
  const [dataTable, setDataTable] = useState(null);
  const metamaskAddress = fetchBlockchainData[0];
  const applicationContract = fetchBlockchainData[2];

  useEffect(() => {
    if (!(metamaskAddress && applicationContract)) return;
    getApplicationsData(applicationContract, metamaskAddress)
      .then((res) => setDataTable(res))
      .catch((err) => console.log(err));
  }, [applicationContract, metamaskAddress]);

  if (dataTable === null) return <div>Loading...</div>;

  // ... render using dataTable...
}

相关问题