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:
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)