Reputation: 119
I'm working on a challenge. My task is to use two APIS: https://api.thecatapi.com/v1/images/search?breed_id=abys and https://api.thecatapi.com/v1/breeds
to display image and description. So far I've got:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'
const Cat = ({ cat: { name, weight, life_span, description } }, { image: url }) => {
return (
<div className='cat'>
<div className='cat_wrapper'>
<img src={url} alt="catimage" />
</div>
<h3 className='cat_breed'>{name.toUpperCase()}</h3>
<div className='country_text'>
<span>Weight:{weight.metric}</span>
<span>Lifespan: {life_span}</span>
<div>Description: {description}</div>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
data2: []
}
componentDidMount() {
this.fetchCatData()
}
fetchCatData = async () => {
const url = 'https://api.thecatapi.com/v1/breeds'
const images = 'https://api.thecatapi.com/v1/images/search?breed_id=abys'
try {
const response = await axios.get(url)
const response2 = await axios.get(images)
const data = await response.data
const data2 = await response2.data2
this.setState({
data, data2
})
} catch (error) {
console.log(error)
}
}
render() {
return (
<div className='App'>
<div>
<p>There are {this.state.data.length} cats in the api</p>
<div className='wrapper'>
{this.state.data.map((cat, image) => (
<Cat image={this.state.data2.image} cat={cat} key={cat.id} />
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
But it returns an error
× TypeError: Cannot read property 'image' of undefined
How to fix it?
-=EDITED=-
so, now it reads the 'url'
key, earlier it was undefined
. I managed to display a hardcoded image of a cat, now I wonder how to map all the different images to its proper contents.
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'
const Cat = ({ cat: { name, weight, life_span, description, url }}) => {
return (
<div className='cat'>
<div className='cat_wrapper'>
<img alt="catimage" src={url} width="50" height="30"/>
</div>
<h3 className='cat_breed'>{name.toUpperCase()}</h3>
<div className='country_text'>
<span>Weight:{weight.metric}</span>
<span>Lifespan: {life_span}</span>
<div>Description: {description}</div>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
data2: []
}
componentDidMount() {
this.fetchCatData()
}
fetchCatData = async () => {
const url = 'https://api.thecatapi.com/v1/breeds'
const images = 'https://api.thecatapi.com/v1/images/search?breed_id=abys'
try {
const response = await axios.get(url)
const response2 = await axios.get(images)
const data = await response.data
const data2 = await response2.data
this.setState({
data, data2
})
} catch (error) {
console.log(error)
}
}
render() {
return (
<div className='App'>
<div>
<p>There are {this.state.data.length} cats in the api</p>
<div className='wrapper'>
{this.state.data.map((cat) => {
cat.url = this.state.data2[0].url;
return <Cat cat={cat} key={cat.id}/>
}
)}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
Upvotes: 0
Views: 280
Reputation: 10382
you better first fetch all data cats then, for each cat make a request to fetch its correspondent image for that cat and add an image or url attribute like:
fetchCatData = async () => {
const catsDataUrl = 'https://api.thecatapi.com/v1/breeds'
const searchImgUrl = 'https://api.thecatapi.com/v1/images/search?breed_id='
try {
const catsResponse = await axios.get(catsDataUrl)
const cats = catsResponse.data
await Promise.allSettled(cats.map(async (cat) => {
const response = await axios.get(`${searchImgUrl}${cat.id}`)
cat.url = response.data[0].url // data is an array with a single object
}))
this.setState({cats}) // I changed state name for cats to be more semantic
} catch (error) {
console.log(error)
}
}
now you don't need data2, you already have url. fwiw, your error is given the fact that data2 is an array and not an object with image
attribute.
Upvotes: 1