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)
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.