为什么在React中状态更改后组件不重新渲染

时间:2018-10-24 00:15:52

标签: javascript reactjs

我正试图从Coin Market Cap API获取数据,并以一些非常基本的卡片显示信息。我尝试了很多事情,并有评论显示了我所测试的内容。请帮忙。

这是父母:

import React, { Component } from 'react';
import './App.css';
import CardList from './CardList';
// a test file for starting off.
// import { coinObj } from './coinObj';


class App extends Component {
  //I have tried with props here too, but don't know why that would matter in the case.
  constructor(props) {
    super(props)
    this.state = {
      coinObj: [],
    }
  }

  //Get information from coinmarketcap api.
  componentDidMount() {
    fetch('https://api.coinmarketcap.com/v2/ticker/')
      .then(response => response.json())
      .then(parsedJSON => this.setState(
        {coinObj: parsedJSON.data}
      ))
      .catch(error => console.log('Something went wrong!', error))

      // .then(coinObj => console.log(coinObj))
  }
  //render cards with data from api
  //The state is changed when I run this with the React Dev tools but it does not render new info.
  render() {
    let { coinObj } = this.state;
    //This console loads twice as expected and the second time it has the object from coinmarketplace.
    console.log(coinObj);

    return !coinObj.length ?
      <h2>Loading</h2> :    
    (
      <div>
        <h1>Coins and Stocks</h1>
        <CardList coinObj={ coinObj } />
      </div>
    );

    //I use this below to try and force the program forward but then I cannot read any values from the object I put in state.
    /*return (
      <div>
        <h1>Coins and Stocks</h1>
        <CardList coinObj={ coinObj } />
      </div>
    );
    */  
  }
}

export default App;

这是一个孩子:

import React from 'react';
import Card from './Card';

const CardList = ({coinObj}) => {
    //This array holds the id of the coins I am interested in.
    const coinsIdArray = [1, 1027, 1958, 2577];
    //This shows me the first object in my object of objects when the cards are commented bottom is out.
    console.log(coinObj[1]);
    //Test if I can grab a value from it and it says that name is undefined but it is clearly their the example above.
    // console.log(coinObj[1].name);


    // send data to the card
    return (
        <div className="container-fluid row">
            <Card name={coinObj[coinsIdArray[0]].name} rank={coinObj[coinsIdArray[0]].rank} price={coinObj[coinsIdArray[0]].quotes["USD"].price} percentChange24={coinObj[coinsIdArray[0]].quotes["USD"].percent_change_24h} />
            <Card name={coinObj[coinsIdArray[1]].name} rank={coinObj[coinsIdArray[1]].rank} price={coinObj[coinsIdArray[1]].quotes["USD"].price} percentChange24={coinObj[coinsIdArray[1]].quotes["USD"].percent_change_24h} />
            <Card name={coinObj[coinsIdArray[2]].name} rank={coinObj[coinsIdArray[2]].rank} price={coinObj[coinsIdArray[2]].quotes["USD"].price} percentChange24={coinObj[coinsIdArray[2]].quotes["USD"].percent_change_24h} />
            <Card name={coinObj[coinsIdArray[3]].name} rank={coinObj[coinsIdArray[3]].rank} price={coinObj[coinsIdArray[3]].quotes["USD"].price} percentChange24={coinObj[coinsIdArray[3]].quotes["USD"].percent_change_24h} />
        </div>
    )
}

export default CardList;

最终孩子:

import React from 'react';

const Card = ({name, rank, price, percentChange24}) => {
    // destructering the data from api to be used.
    // should break up props first but I am trouble shooting other stuff.....................!
    // const {name, rank, price, percentChange24} = props;
    return (
        <div className="card shadow" style={{width: '18rem'}}>
            <img alt='coin/stock logo' src='https://en.bitcoin.it/w/images/en/2/29/BC_Logo_.png' className="mx-auto card-img-top w-50 h-50" />
            <div className="card-body">
                <h2 className="card-title text-center">{name}</h2>
                <h5 className="text-center">{`Rank: ${rank}`}</h5>
            </div>
            <ul className="list-group list-group-flush">
                <li className="list-group-item">{`Price: $${price.toFixed(2)}`}</li>
                <li className="list-group-item">{`Change over 24hrs: ${percentChange24}%`}</li>
            </ul>

        </div>
    )
}

export default Card;

我的第一个问题是让信息从父级传递到组件。我收到错误消息,说coinObj [1] .name未定义。我得出的结论是,它试图在api返回之前获取信息。现在,我无法重新渲染它,这使我想知道在纠正此问题后是否还会遇到该问题。请,谢谢您的帮助。

1 个答案:

答案 0 :(得分:0)

从网络请求中获得的parsedJSON.data是一个对象。所有对象都不像数组那样具有length属性,因此一旦请求完成,!coinObj.length仍将评估为true

您可以改为将初始值从一个空数组更改为null,然后在渲染方法中进行检查:

class App extends Component {
  state = {
    coinObj: null
  };

  // ...

  render() {
    let { coinObj } = this.state;

    return coinObj === null ? (
      <h2>Loading</h2>
    ) : (
      <div>
        <h1>Coins and Stocks</h1>
        <CardList coinObj={coinObj} />
      </div>
    );
  }
}