0

I have the following code, which is returning the error:

"cannot read property 'albumCover' of undefined

Based on the code at line 24.

import React, {Component} from 'react';
import albumData from './../data/albums';

class Album extends Component {
    constructor(props) {
        super(props);

        const album = albumData.find( album => {
            return album.slug === this.props.match.params.slug
        });

        this.state = {
            album: album
        };
    }

    render() {
        return (
            <section className ="album">
                <section id="album-info">
                    <img id="album-cover-art" src={this.state.album.albumCover} /> <- error
                    <div className="album-details">
                        <h1 id="album-title"></h1>
                        <h2 className="artist"></h2>
                        <div id="release-info"></div>
                    </div>
                </section>
          </section>
        );
    }
}

export default Album

My understanding is that this is due to a problem with the context of 'this' not being set correctly, but as far as I can see, this code should execute correctly. Can anyone tell my why I'm getting the error, and how to set the right context for 'this'?

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
Muskett
  • 490
  • 1
  • 5
  • 14
  • Did you log your album in render to be sure that this.state.album is set ? – ChrisR Feb 05 '18 at 10:59
  • I suppose this will help you https://stackoverflow.com/questions/45468837/get-path-params-in-react-router-v4/45469647#45469647 or perhaps this https://stackoverflow.com/questions/47221853/react-router-dom-link-change-url-but-does-not-render/47222270#47222270 – Shubham Khatri Feb 05 '18 at 11:04
  • after render before return try to console.log(this.state) and verify the state – Rajat Dhoot Feb 05 '18 at 11:05

3 Answers3

1

If you see how #array.find works, it will return undefined if all the elements fails the condition, otherwise return that single element.

As per MDN DOC:

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

Check this snippet (find will return undefined):

let a = [1,2,3,4,5].find(el => el>5);

console.log('a = ', a);   // will be undefined

That's why you are getting the error, when you are trying to access the property of undefined:

cannot read property 'albumCover' of undefined.

Solution:

Use Short circuit evaluation concept and put || {}, if find returns undefined, it will assign the {} blank object to album value.

Like this:

this.state = {
     album: album || {},
};

And use it like this:

src={this.state.album.albumCover || ''}

Or use album || {src: ''}:

this.state = {
    album: album || {src: ''}
}
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
0

One of the fix for this problem could be

 <img id="album-cover-art" alt="some-default-image" src={this.state.album ? this.state.album.albumCover : ''} /> <- error
mu_sa
  • 2,685
  • 10
  • 39
  • 58
0

Your props area being passed in here as a parameter, so rather than trying to access via this.props, just access the parameter directly.

constructor(props) {
    super(props);

    const album = albumData.find( album => {
        return album.slug === props.match.params.slug
    });

    this.state = {
        album: album
    };
}

Also then you will want to check to see if you then have an album set in the state properly before trying to read from it.

Tim B James
  • 20,084
  • 4
  • 73
  • 103