如何使用JavaScript(React.js)实现随代币供应量动态扩容的智能合约数据表格?
Hey there! Let's get that dynamic, auto-expanding table up and running for your graduation tokenization project. You've already nailed fetching the data to the console—nice work! Here's how to translate that into a clean, responsive table that grows as new tokens are minted.
Step 1: Set Up Your HTML Table Structure
First, add a basic table to your HTML. We'll use a fixed header and an empty body where we'll inject our token rows:
<table id="tokenTable" border="1" cellpadding="8" cellspacing="0"> <thead> <tr> <th>Token ID</th> <th>Owner Address</th> <th>Loan Amount</th> <th>Rate</th> <th>Term</th> <th>Start Date</th> <th>End Date</th> </tr> </thead> <tbody id="tokenTableBody"> <!-- Dynamic rows will go here --> </tbody> </table>
Step 2: Rewrite Your Data Fetching & Table Rendering Code
Your current code has a couple of small issues (like using async/await inside forEach, which doesn't handle async operations properly) and needs to be adjusted to build table rows instead of logging to the console. Here's the revised version:
// Get reference to the table body once const tableBody = document.getElementById('tokenTableBody'); // Helper function to convert timestamp to readable date const formatTimestamp = (timestamp) => { return new Date(timestamp * 1000).toLocaleString(); }; // Function to fetch and render all token data const fetchAndRenderTokens = async () => { // Clear existing rows first (optional, prevents duplicates on refresh) tableBody.innerHTML = ''; // Get total supply and build index list const limit = await callsupplyfunction(); const totalTokens = Number(limit); const tokenList = []; // Fetch all token IDs for (let i = 0; i < totalTokens; i++) { const tokenId = await a(i); // Assuming `a()` is your function to get token ID from index tokenList.push(tokenId); } // Loop through each token and build table rows for (const tokenId of tokenList) { // Fetch all data for this token in parallel to speed up loading const [owner, amount, rate, term, startTimestamp, endTimestamp] = await Promise.all([ contract.methods.ownerOf(tokenId).call(), contract.methods.getLoanAmount(tokenId).call(), contract.methods.getRate(tokenId).call(), contract.methods.getTerm(tokenId).call(), contract.methods.getStartDate(tokenId).call(), contract.methods.getEndDate(tokenId).call() ]); // Create a new table row const row = document.createElement('tr'); // Populate row with formatted data row.innerHTML = ` <td>${tokenId}</td> <td>${owner}</td> <td>${amount}</td> <td>${rate}</td> <td>${term}</td> <td>${formatTimestamp(startTimestamp)}</td> <td>${formatTimestamp(endTimestamp)}</td> `; // Add the row to the table body tableBody.appendChild(row); } }; // Initial load when the script runs fetchAndRenderTokens();
Key Improvements Here:
Promise.all(): Fetches all token data points in parallel instead of sequentially, cutting down on load time.for...ofinstead offorEach: Properly handlesasync/awaitso rows render in the correct order.- Direct DOM Manipulation: Creates valid table elements instead of using the non-functional
HTMLTableRowElement.applycall. - Timestamp Formatting: Converts raw Unix timestamps from the contract into human-readable dates.
Step 3: Make the Table Auto-Expand When New Tokens Are Minted
To automatically update the table when new tokens are created, pick one of these two reliable options:
Option 1: Listen for Contract Events
If your smart contract emits a Mint (or similar) event when new tokens are created, listen for that event to trigger a refresh:
// Listen for Mint event (adjust the event name to match your contract's actual event) contract.events.Mint() .on('data', async () => { console.log('New token minted! Refreshing table...'); await fetchAndRenderTokens(); }) .on('error', (error) => console.error('Event listener error:', error));
Option 2: Periodic Refresh (Fallback)
If event listening isn't feasible, set up a timer to refresh the table at regular intervals (e.g., every 10 seconds):
// Refresh table every 10 seconds (10000 milliseconds) setInterval(async () => { await fetchAndRenderTokens(); }, 10000);
Bonus Tips for Polish
- Add a Loading State: Show a spinner or "Loading..." text while data is being fetched to improve user experience.
- Truncate Long Addresses: Shorten wallet addresses to something like
0x123...456to save table space. - Style with CSS: Add hover effects, alternating row colors, or responsive design to make the table look professional.
内容的提问来源于stack exchange,提问作者ismaeel adams

