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

getInitialProps中Async对象成功获取却无法渲染问题求助

Fixing 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

  1. Change coinObjects to 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 {}
    
  2. Update the render logic to count object keys
    Objects don't have a built-in length property. To get the number of coins, use Object.keys() to extract all the keys from coinObjects, 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>
      );
    }
    
  3. 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 to coinObjects too, 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:34:48