getInitialProps中Async对象成功获取却无法渲染问题求助
coinObjects.length Showing 0 in React/Next.js Component Hey there! Let's break down why your coinObjects isn't displaying the correct length, even though console.log shows the data is there.
The Core Issue
You initialized coinObjects as an array (const coinObjects = [];), but then you're using string keys (like "NEO", "ETH") to assign data to it:
coinObjects[coinList[i]] = res[i].data.Data;
In JavaScript, arrays only count elements with numeric indexes towards their length property. Adding string-keyed properties to an array doesn't add to its length—it just attaches extra data to the array object itself. That's why console.log shows the data, but length returns 0.
Your linksArr works fine because you're using push() to add elements with numeric indexes, which the array properly counts.
Step-by-Step Fix
Change
coinObjectsto a plain object
Initialize it as an object instead of an array—this is the right structure for key-value pairs where keys are strings (like coin symbols):const coinObjects = {}; // Replace [] with {}Update the render logic to count object keys
Objects don't have a built-inlengthproperty. To get the number of coins, useObject.keys()to extract all the keys fromcoinObjects, then get the length of that array:render() { return ( <Layout> <h2> CoinObject has {Object.keys(this.props.coinObjects).length} coins {/* Now returns 3 */} <br /> LinksArr has {this.props.linksArr.length} links {/* Still returns 3 */} </h2> </Layout> ); }Optional: Adjust client-side return (if needed)
Right now, you return an empty object for client-side. If you want the client to have access tocoinObjectstoo, return the same data as the server:if (isServer) { return { coinObjects, numCoins, linksArr }; } else { return { coinObjects, numCoins, linksArr }; // Match server return }
Full Modified Code Snippet
class MainIndex extends Component { static async getInitialProps(props) { // setup - empty object and list of coins const coinList = ["NEO", "ETH", "BTC"]; const numCoins = coinList.length; const coinObjects = {}; // Changed from array to object const linksArr = []; const isServer = typeof window === "undefined"; // API GET const baseUrl = "https://min-api.cryptocompare.com/data/histohour?"; for (let coinName of coinList) { linksArr.push( baseUrl.concat("fsym=", coinName, "&tsym=", "USD", "&limit=", "3") ); } const getObj = async linksArr => { try { let res = await axios.all(linksArr.map(l => axios.get(l))); for (let i = 0; i < linksArr.length; i++) { coinObjects[coinList[i]] = res[i].data.Data; // This logic stays the same } } catch (err) { console.error(err); } }; await getObj(linksArr); console.log(coinObjects); // Return updated data if (isServer) { return { coinObjects, numCoins, linksArr }; } else { return { coinObjects, numCoins, linksArr }; // Optional: match server return for client } } render() { return ( <Layout> <h2> CoinObject has {Object.keys(this.props.coinObjects).length} coins <br /> LinksArr has {this.props.linksArr.length} links </h2> </Layout> ); } }
Bonus: Accessing the Coin Data Later
If you need to render each coin's data, you can use Object.entries() to loop through the key-value pairs:
// Example in render() {Object.entries(this.props.coinObjects).map(([coinName, coinData]) => ( <div key={coinName}> <h3>{coinName}</h3> {/* Render coinData here */} </div> ))}
内容的提问来源于stack exchange,提问作者Edmond Tam

