从父级组件传递道具在子级组件React中为空

时间:2020-10-13 08:19:19

标签: javascript reactjs

我正在制作一个简单的React网站,该网站从API(this API)获取一些数据,然后将其显示在页面上。我使用的端点是skyblock/auctions端点。返回的是对象列表,我想要获取其中的第一个对象,然后将其传递给子组件。父级可以成功获取数据,但是当我将其传递给子级并console.log时,它将返回null。我能想到的唯一原因是父组件尚未完成数据的获取,但是我不确定如何使其仅在完成后才呈现。

以下是父组件AuctionViewer的代码:

class AuctionViewer extends Component {
  state = { data: null}

  loadData = async () => {
    let url = "https://api.hypixel.net/skyblock/auctions?key=INSERT_KET_HERE" 
    let response = await fetch(url);
    let json = await response.json();

    this.setState({data: json.auctions[0]}, function () {
      console.log(this.state.data)
    });
  }

  componentDidMount() {
    this.loadData();
    setInterval(this.loadData, 60 * 1000);
  }

  render() { 
    return (<Auction data={this.state.data} />);
  }
}

这是子组件Auction

class Auction extends Component {
  state = {
    loading: true,

    item: null,
    price: null,
    startPrice: null,
    time: null,
  };

  loadData() {
    let data = this.props.data;
    console.log(data);

    let end = new Date(data.end - Date.now());
    let timeLeft = end.getHours() + ":" + end.getMinutes() + ":" + end.getSeconds();     
    this.setState({loading: false, item: data.item_name, price: data.highest_bid_amount, startPrice: data.starting_bid, time: timeLeft, timestamp: end});
  };

  componentDidMount() {
    this.loadData();
  }

  render() {
    return (
      <div className="gridBox">
        {this.state.loading ? (
          <p>Loading...</p>
        ) : (
          <div>
            <p>Item: {this.state.item}</p>
            <p>Top Bid: {this.state.price}</p>
            <p>Start Bid: {this.state.startPrice}</p>
            <p>Time Left: {this.state.time}</p>
          </div>
        )}
        <button onClick={this.loadData}>Refresh</button>
      </div>
    );
  }
}

2 个答案:

答案 0 :(得分:1)

我能想到的唯一原因是父组件尚未完成数据的获取...

是的。

...但是我不确定如何使其仅在完成后呈现。

您有两个选择:

  1. (我认为您不想要这个。)将ajax调用移到父组件的父组件中,并且仅在拥有数据时才渲染父组件。 / p>

  2. 让父组件呈现某种“正在加载”状态,直到数据可用为止

#2看起来像这样:

render() { 
  const { data } = this.state;
  return (data ? <Auction data={data} /> : <em>Loading...</em>);
}

...但可能具有比<em>Loading...</em>更有吸引力的功能。 :-)

答案 1 :(得分:0)

最简单的方法是在#define SIZE 10 void fun(int arr[]){ int i,k,j,n = SIZE; k = 0; // walk through the array up until its 10th element, skipping // the first entry and hoping that the array actually contains // at least 10 entries for (i = 1 ; i < SIZE; i++) { // similar to i, the variable k also walks up towards 10. // However it starts at 0, not at 1, and it does not // necessarily get incremented in every loop iteration. More // on that below. // Here, we set the variable j to start out as the same value // as the current k, but j will walk the opposite direction, i.e., // toward 0, not toward 10. j = k; // find the largest j in the open interval [0,k) for which // the array entry arr[j] differs from the current arr[i] while (j > 0 && arr[j] != arr[i]) j = j - 1; // if no value in [0, k) was equal to arr[i], we'll end up \ // with j == 0 if( j == 0){ // then we increment k -- that is, k counts how many times // we encountered a value arr[i] during the for-loop that was // unique among the first i array entries. But since the // for loop starts at 1 instead of 0, k will count one // element too few. k = k + 1; // well, so much for 'unique': here, we actually copy the current // value arr[i] into arr[k] arr[k] = arr[i]; } else // this part in effect assures that the expression // (n-k) gets decremented in every iteration of the loop, // no matter if j == 0 is true or false. // Since we start out with (n-k) = SIZE, and // the loop body gets executed SIZE-1 times, (n-k) will // be equal to 1 after the for-loop has terminated. n--; } } “获取”数据时进行一些条件渲染。初始状态为AuctionViewer,并将其传递给null,但是您可以在等待时有条件地呈现其他UI或为null。

Auction

或返回null表示不应该渲染任何内容。

render() { 
  const { data } = this.state;
  return data ? (
    <Auction data={data} />
  ) : <div>Loading...</div>;
}