开发者问题收集

未捕获(在承诺中)TypeError:无法读取未定义的属性“图像”(…)

2016-11-04
4883

我正在学习 React,但不确定如何解决我的问题。我正在从 Reddit 导入数据。我能够从 JSON 数据中输出标题和 ID,但当我尝试对图片网址执行相同操作时,我得到了 Uncaught (in promise) TypeError: Cannot read property 'images' of undefined(…)。

这是我的代码(变量filteredPosts 是发生错误的地方),下面我将包含 JSON 文件的一部分:

import React from "react";
import Projects from "./Projects";
import axios from 'axios';

export default class MainContainer extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            posts: []
        }

    }

    componentDidMount(){
        axios.get('https://www.reddit.com/r/reactjs.json')
        .then(res => {
            const posts = res.data.data.children.map(obj => obj.data);
            this.setState({posts});
        })

    }

    render() {

        var filteredPosts = this.state.posts.map(post => <Projects key={post.id} title={post.title} imgSrc={post.preview.images[0].source.url}></Projects>);

        return (
        <div>
            <div className="container">
                <div className="row">
                    <div className="col-lg-12">
                        <h1 className="page-header">My Project
                            <small> made with React.js</small>
                        </h1>
                    </div>
                </div>
                <div className="row">
                        {filteredPosts}
                </div>
                <hr/>
                <div className="row text-center">
                    <div className="col-lg-12">
                        <ul className="pagination">
                            <li>
                                <a href="#">&laquo;</a>
                            </li>
                            <li className="active">
                                <a href="#">1</a>
                            </li>
                            <li>
                                <a href="#">2</a>
                            </li>
                            <li>
                                <a href="#">3</a>
                            </li>
                            <li>
                                <a href="#">4</a>
                            </li>
                            <li>
                                <a href="#">5</a>
                            </li>
                            <li>
                                <a href="#">&raquo;</a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
        );
    }
}

和 JSON 数据的一部分

{
  "kind": "Listing",
  "data": {
    "modhash": "",
    "children": [
      {
        "kind": "t3",
        "data": {
          "contest_mode": false,
          "banned_by": null,
          "domain": "appendto.com",
          "subreddit": "reactjs",
          "selftext_html": null,
          "selftext": "",
          "likes": null,
          "suggested_sort": null,
          "user_reports": [

          ],
          "secure_media": null,
          "saved": false,
          "id": "5b4ly7",
          "gilded": 0,
          "secure_media_embed": {

          },
          "clicked": false,
          "report_reasons": null,
          "author": "kylebythemile",
          "media": null,
          "name": "t3_5b4ly7",
          "score": 12,
          "approved_by": null,
          "over_18": false,
          "removal_reason": null,
          "hidden": false,
          "preview": {
            "images": [
              {
                "source": {
                  "url": "https:\/\/i.redditmedia.com\/SQmtP8sZ_KVQ7ro86Nxtqbm7pv_9vGRYQasz4WHkcno.jpg?s=666b08d702fd9102b613696796eb024a",
                  "width": 300,
                  "height": 140
                },
                "resolutions": [
                  {
                    "url": "https:\/\/i.redditmedia.com\/SQmtP8sZ_KVQ7ro86Nxtqbm7pv_9vGRYQasz4WHkcno.jpg?fit=crop&amp;crop=faces%2Centropy&amp;arh=2&amp;w=108&amp;s=8ad5dbf3e11f262813db5ae0abde322b",
                    "width": 108,
                    "height": 50
                  },
                  {
                    "url": "https:\/\/i.redditmedia.com\/SQmtP8sZ_KVQ7ro86Nxtqbm7pv_9vGRYQasz4WHkcno.jpg?fit=crop&amp;crop=faces%2Centropy&amp;arh=2&amp;w=216&amp;s=35c1ca12d95578caf11c525dc8344197",
                    "width": 216,
                    "height": 100
                  }
                ],
                "variants": {

                },
                "id": "6-DU1uRDjVj1MLweYNbxm9T8aMz-XOV8yO5aoKkR1FI"
              }
            ]
          },
          "thumbnail": "http:\/\/b.thumbs.redditmedia.com\/mmhbul366OESsJ0BNfSq5rCUsJq74s7R40zzlzwpH6w.jpg",
          "subreddit_id": "t5_2zldd",
          "edited": false,
          "link_flair_css_class": null,
          "author_flair_css_class": null,
          "downs": 0,
          "mod_reports": [

          ],
          "archived": false,
          "media_embed": {

          },
          "post_hint": "link",
          "is_self": false,
          "hide_score": false,
          "spoiler": false,
          "permalink": "\/r\/reactjs\/comments\/5b4ly7\/build_a_coffee_finder_app_with_react_native_and\/",
          "locked": false,
          "stickied": false,
          "created": 1478306294,
          "url": "https:\/\/appendto.com\/2016\/11\/build-a-coffee-finder-app-with-react-native-and-the-yelp-api\/?reddit",
          "author_flair_text": null,
          "quarantine": false,
          "title": "Build a Coffee Finder App with React Native and the Yelp API",
          "created_utc": 1478277494,
          "link_flair_text": null,
          "distinguished": null,
          "num_comments": 0,
          "visited": false,
          "num_reports": null,
          "ups": 12
        }
      },
1个回答

问题是您假设每篇帖子都会有一个预览属性。我自己进行了 ajax 调用,并对每篇帖子进行了控制台日志记录,发现至少有 6 篇没有预览属性。

您需要更加谨慎,并使用默认图像或空白背景。您可以执行以下操作:

imgSrc={post.preview ? post.preview.images[0].source.url : defaultImg

假设您有一个 defaultImg,如果没有,则返回一个空字符串。

还有一个假设,如果预览属性存在,则图像属性也将存在以及 source.url。深入研究您正在使用的 api 以查看其一致的地方以及不一致的地方以及不一致性的地方,总是好的,通过检查子属性之前是否存在属性来进行更具防御性的编程。

另外,作为最后一个选项,如果您只想要带有预览的帖子,您可以做一个简单的过滤:

this.state.posts.filter((post) => post.preview) // returns only posts with preview property
finalfreq
2016-11-04