1

I am trying to get data from part of an api which is like this and actually i can see the all data in the console.

{ 
  "id":"DszAeHV8zfQ",
  "created_at":"2020-01-28T19:41:06-05:00",
  "updated_at":"2020-01-29T05:54:02-05:00",
  "promoted_at":"2020-01-29T05:54:02-05:00",
  "width":3887,
  "height":5595,
  "color":"#1E130A",
  "description":"Yet another sleeping koala. I am not happy with the lighting in this photo, where the koala is in the deep shade of an orange/brown tarpaulin (which is needed to give them shelter from the rain and the sun), and the bright light background, but I can't help being amused by the way they can sleep anywhere in any position.",
  "alt_description":null,
  "urls":{ 
     "raw":"https://images.unsplash.com/photo-1580258387643-65bb85ef9c61?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMjkzNX0",
     "full":"https://images.unsplash.com/photo-1580258387643-65bb85ef9c61?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjExMjkzNX0",
     "regular":"https://images.unsplash.com/photo-1580258387643-65bb85ef9c61?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExMjkzNX0",
     "small":"https://images.unsplash.com/photo-1580258387643-65bb85ef9c61?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjExMjkzNX0",
     "thumb":"https://images.unsplash.com/photo-1580258387643-65bb85ef9c61?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjExMjkzNX0"
  },
  "links":{ 
     "self":"https://api.unsplash.com/photos/DszAeHV8zfQ",
     "html":"https://unsplash.com/photos/DszAeHV8zfQ",
     "download":"https://unsplash.com/photos/DszAeHV8zfQ/download",
     "download_location":"https://api.unsplash.com/photos/DszAeHV8zfQ/download"
  },
  "categories":[ 

  ],
  "likes":2,
  "liked_by_user":false,
  "current_user_collections":[ 

  ],
  "user":{ 
     "id":"TYLyWjPA9BM",
     "updated_at":"2020-01-29T05:54:02-05:00",
     "username":"davidclode",
     "name":"David Clode",
     "first_name":"David",
     "last_name":"Clode",
     "twitter_username":null,
     "portfolio_url":"http://tracts4free.wordpress.com",
     "bio":"I enjoy photography, painting, and nature. I lived in South Africa, the UK, and now Australia. More free paintings, photos available at Tracts4Free.WordPress.com, and Reforestation.me. Also now on YouTube.",
     "location":"Cairns, Queensland, Australia.",
     "links":{ 
        "self":"https://api.unsplash.com/users/davidclode",
        "html":"https://unsplash.com/@davidclode",
        "photos":"https://api.unsplash.com/users/davidclode/photos",
        "likes":"https://api.unsplash.com/users/davidclode/likes",
        "portfolio":"https://api.unsplash.com/users/davidclode/portfolio",
        "following":"https://api.unsplash.com/users/davidclode/following",
        "followers":"https://api.unsplash.com/users/davidclode/followers"
     },
     "profile_image":{ 
        "small":"https://images.unsplash.com/profile-1503350572760-b44aa5280785?ixlib=rb-1.2.1&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32",
        "medium":"https://images.unsplash.com/profile-1503350572760-b44aa5280785?ixlib=rb-1.2.1&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64",
        "large":"https://images.unsplash.com/profile-1503350572760-b44aa5280785?ixlib=rb-1.2.1&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128"
     },
     "instagram_username":null,
     "total_collections":11,
     "total_likes":16469,
     "total_photos":676,
     "accepted_tos":true
  }

}

I can get "id", "created_at" fields. but i can't get those nested objects like "urls", "links"

I have tried to get that data using object notation like this:

<img src={this.state.photo.urls.raw} alt="" />

But it gives me an error:

TypeError: Cannot read property 'raw' of undefined 

My fetch function is like this:

 getPhoto = () => {
    fetch(`https://api.unsplash.com/photos/${this.state.photoId}?client_id=API_KEY`)
        .then(res => res.json())
        .then(data => {
            this.setState({ photo: data });
            console.log(this.state.photo);
        })
        .catch(err => console.log(err));
}

My states:

constructor(props) {
    super(props);
    this.state = {
        photo: [],
        photoId: this.props.match.params.photoId,
    }
}

1 Answer 1

1

This happens because in the first render, this.state.photo is an array

constructor(props) {
    super(props);
    this.state = {
        photo: [],
        photoId: this.props.match.params.photoId,
    }
}

And doesn't have the property url.

To fix it you should

Change the photo to and object

constructor(props) {
    super(props);
    this.state = {
        photo: {}, // object
        photoId: this.props.match.params.photoId,
    }
}

Check if this.state.photo.url exists before accessing it

<img src={this.state.photo.urls && this.state.photo.urls.raw} alt="" />

You could also have a default src when the image haven't loaded yet.

<img src={this.state.photo.urls ? this.state.photo.urls.raw : 'default url'} alt="" />
Sign up to request clarification or add additional context in comments.

4 Comments

When i convert it from array to object it is not working neither. But when i change <img src={this.state.photo.urls.raw} alt="" /> to <img src={this.state.photo.urls && this.state.photo.urls.raw} alt="" /> it works. Why is that works?
Is it happening because of this.state.photo.urls didn't loaded properly immediately? Why do i have to check if this.state.photo.urls true?
Yes, it's because it didn't loaded immediately. You are making an async call ( api call ) and it takes some time to get the data. What is happening here is that on the first render of your component, this.state.photo is the value you put on the constructor and only after the async call finishes, you set the state whici makes the component rerender with the correct data. On the first render, this.state.photo is [] and you can't do [].url.raw beucause [].url is undefined and you can't access a property from undefined.
One thing you could do is set in the constructor this.state = { photo: { url: { raw: 'default-url' } } } And this way you don't need to do the checking, but is much better you do the checking because if you api request returns something different from what you are expecting, it will give the same error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.