javascriptarraysreact-nativeexpogoogle-books

How to filter an array by ignoring elements with undefined properties?


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.


Solution

  • 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')