简体   繁体   中英

How can I make my React child components render even if a prop is missing

TLDR; I need to be able to render child components in React even if a property of this.props is missing.

I have an React app built with Yahoo's Flxubile . The app fetches data from a Wordpress site with WP REST API. Sometimes an image might be missing or something else from the API, this causes the client to break. Here's an example:

I have a file called Articles.js which is connected to ArticlesStore which holds my articles. I then render one Article.js for every article I have and pass props like this:

{   this.props.articles.map(function(el, index) {                                           
      return <Article key={index} article={el} />
    })
}

Everything is ok here, but then in my Article.js when I try to access properties that is not set I get the following:

Uncaught TypeError: Cannot read property 'sizes' of undefined

This is the line which causes the error:

<img src={this.props.article.meta_fields.image.sizes.large} />

This happens when a image is missing from an article. I understand the javascript error of course but I want to render the Article.js component event if a image url is missing from the API/Store. I have tried the following solutions, but it causes too much clutter and no control:

  1. Conditional set if we have the prop ie {this.props.article.meta_fields.image ? this.props.article.meta_fields.image.sizes.large : "imagemissing.png"}
  2. Setting defaultProps. This does not work because passed properties from parent to child overwrites defaultProps.

Maybe I should try something else than passing props from parent to child? Have a ArticleStore where I can set default values for every article? How would you do it?

If you want to provide a nested structure as a prop (as with article ) you'll want to be able to rely on the structure always being pretty much the same. In this case it won't be, sometimes the meta_fields does not have an image -attribute (as your TypeError suggests).

In your case I would consider pulling out the things you actually need/use in the Article component from the article object and pass those as props.

Say that your Article only uses title , body , and image . Then just pass those as props.

<Article title={ article.title } body={ article.body } image={ getImage(article) }/>

function getImage(article) {
    if (article.meta_fields.image
     && article.meta_fields.image.sizes
     && article.meta_fields.image.sizes.large
    ) {
        return article.meta_fields.image.sizes.large;
    }
    return 'default_image.jpg'; // Or whatever you want.
}

One might think that the extra props constitutes more "clutter" here, but given the choice between clutter and TypeError , I choose clutter.

And if you don't want to reinvent the wheel. The problem of accessing data in a nested structure like this have been solved before.

// Lodash
_.get(article, 'meta_fields.image.sizes.large', 'default_image.jpg')
// Ramda
_.pathOr('default_image.jpg', ['meta_fields', 'image', 'sizes', 'large'], article)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM