未捕获(承诺)TypeError:无法读取未定义的属性'图像'(...)

问题描述:

我正在学习React,不知道如何解决我的问题。我从Reddit导入数据。我能够从JSON数据中输出标题和id,但是当我尝试对图像url做同样的处理时,我得到Uncaught(承诺)TypeError:无法读取未定义(...)的属性'图像'。未捕获(承诺)TypeError:无法读取未定义的属性'图像'(...)

这是我的代码(变量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 
     } 
     }, 

问题是,你假设每一个职位将有一个预览属性。我做了自己的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