在获取反应时呈现未定义的对象

时间:2020-06-02 16:14:53

标签: reactjs typescript object undefined

我正在使用coinmarketcap api构建一个简单的加密货币应用程序。我的get请求在componentDidMount内部。当我console.log在异步函数内部和在渲染内部接收到的对象时-它起作用。但是当我实际尝试在return(h3元素)中显示接收到的数据时,接收到的对象变得不确定。我收到一个typeError“无法读取未定义的属性url”。我在这里做什么错了?

import React, { Component } from "react";
import axios from "axios";
import { Row, Col, Badge } from "react-bootstrap";

class Crypto extends Component {
  constructor(props) {
    super(props);
    this.state = {
      singleCrypto: {},
      id: this.props.match.params.id
    };
  }

  componentDidMount() {
    this.getEachCrypto();
  }

  async getEachCrypto() {
    try {
      const proxyurl = "https://cors-anywhere.herokuapp.com/";
      const id = this.props.match.params.id;
      let data = await axios.get(
        proxyurl +
          "https://pro-api.coinmarketcap.com/v1/cryptocurrency/info?id=" +
          id,
        {
          headers: {
            "X-CMC_PRO_API_KEY": "e1eb1f30-5c4e-43aa-be04-4b50df00807a"
          }
        }
      );
      this.setState({ singleCrypto: data.data.data });
    } catch (error) {
      console.log("request failed", error);
    }
    console.log(
      this.state.singleCrypto[this.props.match.params.id].urls.website[0]
    ); // this works
  }

  render() {
    const { singleCrypto } = this.state;

    if (Object.keys(singleCrypto).length === 0) {
      console.log("Loading");
    } else {
      console.log(singleCrypto[this.props.match.params.id].urls.website[0]); // this works
    }

    return (
      <div>
        <div className="crypto fluid">
          <Row>
            <Col lg md={3}>
              <h3>
                {singleCrypto[this.props.match.params.id].urls.website[0]} // fails!!!
              </h3>
              <div>
                <ul>
                  <li>Rank</li>
                  <li>Website</li>
                  <li>Explorer</li>
                  <li>Message Board</li>
                  <li>Source Code</li>
                  <li>Tech Docs</li>
                  <li>Tags</li>
                </ul>
              </div>
            </Col>
            <Col lg md={7}>
              <h3>Price, % change</h3>
              <Badge variant="primary">Buy</Badge>
              <Badge variant="primary">Exchange</Badge>
              <Badge variant="primary">Gamble</Badge>
              <Badge variant="primary">Earn Crypto</Badge>
            </Col>
            <Col lg md={2}>
              2 parts
            </Col>
          </Row>
        </div>
      </div>
    );
  }
}

export default Crypto;

这是我的数据示例:

"data": {
        "1": {
            "urls": {
                "website": [
                    "https://bitcoin.org/"
                ],
                "technical_doc": [
                    "https://bitcoin.org/bitcoin.pdf"
                ],
                "twitter": [],
                "reddit": [
                    "https://reddit.com/r/bitcoin"
                ],
                "message_board": [
                    "https://bitcointalk.org"
                ],

1 个答案:

答案 0 :(得分:1)

当数据不可用时,您必须return nullloading state

if (Object.keys(singleCrypto).length === 0) {
  return null; // you can maintain a loading state too untill data is available
} 

处于加载状态

class Crypto extends Component {
  constructor(props) {
    super(props);
    this.state = {
      singleCrypto: {},
      id: this.props.match.params.id.
      isLoading: true,
    };
  }

  componentDidMount() {
    this.getEachCrypto();
  }

  async getEachCrypto() {
    try {
      const proxyurl = "https://cors-anywhere.herokuapp.com/";
      const id = this.props.match.params.id;
      this.setState({isLoading: true});
      let data = await axios.get(
        proxyurl +
          "https://pro-api.coinmarketcap.com/v1/cryptocurrency/info?id=" +
          id,
        {
          headers: {
            "X-CMC_PRO_API_KEY": "e1eb1f30-5c4e-43aa-be04-4b50df00807a"
          }
        }
      );
      this.setState({ singleCrypto: data.data.data, isLoading: false });
    } catch (error) {
      console.log("request failed", error);
      this.setState({ isLoading: false });
    }
  }

  render() {
    const { singleCrypto } = this.state;
    if(this.state.isLoading) {
        return <div>Loading...<div>
    }
    ...
  }
}

export default Crypto;