1

I am trying to map image URLs to an avatar component. The data I am using is coming from an Google Books API. The data resource is an array of objects (books). Some objects have missing values for the "thumbnail" field I am targeting.

I want to IGNORE these objects if they do not have a value for "thumbnail" and continue mapping through the array.

I am using React Native and Expo

I have tried various methods mentioned on Stack Overflow, including array.filter() with logic on my data before array.map(). None of the recommended solutions have worked.

The error I recieve is:

TypeError: TypeError: undefined is not an object(evaluating 'url.volumeInfo.imageLink.thumbnail')

It appears I can't even have that path inside of an "if" statement, which is strange to me - because even if that value is undefined, why should that matter?

renderCategory() {

        if (this.props.adventure.payload[0]) {
        const fetched_Book = this.props.adventure.payload;
        const filteredThumbnails = fetched_Book.filter(url =>{

           // The console log below shows 4 urls before it fails)
            console.log('URL', url.volumeInfo.imageLinks.thumbnail)

            if(typeof url.volumeInfo.imageLinks.thumbnail === "undefined"){
                return false
            }
            else return true;
            })
        const allThumbnails= filteredThumbnails.map(book => book.volumeInfo.imageLinks.thumbnail);
        return (
            <>
                <View style={styles.thumbnailContainer}>
                    {
                        allThumbnails.map((l, i) =>
                            <Avatar
                                key={i}
                                size="large"
                                source={{ uri: l }}
                                style={styles.thumbNail}
                                onPress={() => this.onSelectedBook(fetched_Book, i)}
                            />
                        )
                    }
                </View>

            </>
        )
    }
    else return ''
    }

The expected output is a new, filtered array of objects, that can then be mapped into my Avatar Component.

jmedran
  • 99
  • 1
  • 10
  • Most likely the `imageLink` or `volumeInfo` field doesn't exist in some case. So you are calling `unknown.thumbnail` that gives you an error – chakwok Jul 22 '19 at 01:57
  • @Andyk. Thank you for the comment! You are correct, checking if the imageLinks property existed solved my issue. Do you have a recommendation for scaling this? I have observed the Google Books API is rather volatile with random cases of missing data. It doesn't seem I can check for every instance of a missing value all the way through a large object in an efficient manner. – jmedran Jul 22 '19 at 02:05
  • [There](https://stackoverflow.com/questions/23808928/javascript-elegant-way-to-check-nested-object-properties-for-null-undefined) are several ways to do so. Unless you have objects nesting 5 level+, I think it is okay to just simply check `if(url.volume.imageLink && url.volume.imageLink.thumbnail)` – chakwok Jul 22 '19 at 02:13
  • @Andyk. I appreciate the help & the useful link – jmedran Jul 22 '19 at 02:24
  • I am glad that helps. Remember to upvote answer that you find helpful and downvote low-quality one's, so people who visited later may find useful info easily. – chakwok Jul 22 '19 at 02:27

1 Answers1

0

This error means that some part of path to thumbnail does not exist so you need to check if each part of that path exists:

const filteredThumbnails = fetched_Book
  .filter(url => !!url && !!url.volumeInfo && !!url.volumeInfo.imageLinks && typeof url.volumeInfo.imageLinks.thumbnail === 'undefined')
Xesenix
  • 2,418
  • 15
  • 30