Reputation:
I am using Axios to get API data in ReactJS. I set up a search query that will take the user input and match it with the API where the data response is set as a state. I am having an issue where if the data I'm trying to receive does not exist in the API, the page returns with this error:
Unhandled Rejection (TypeError): Cannot read property 'medium' of null
32 | title: response.data.name,
33 | summary: response.data.summary,
34 | rating: response.data.rating.average,
> 35 | image: response.data.image.medium,
36 | genre: response.data.genres,
37 | });
38 | })
Is there a way to write and if/else statement inside the GET request to fix this problem?
import React, { Component } from 'react';
import SearchResults from '../SearchResults/SearchResults';
import AddButton from '../AddButton/AddButton';
import axios from 'axios';
class Searchbar extends Component {
constructor(props) {
super(props);
this.state = {
searchTerm: ' ',
title: ' ',
summary: ' ',
rating: ' ',
image: ' ',
genre: [],
}
}
componentWillMount() {
this.search();
}
updateSearchHandler = (event) => {
this.search(this.refs.query.value);
}
search(query = "stranger-things") {
const url = `http://api.tvmaze.com/singlesearch/shows?q=${query}`;
axios.get(url).then(response => {
this.setState({
title: response.data.name,
summary: response.data.summary,
rating: response.data.rating.average,
image: response.data.image.medium,
genre: response.data.genres,
});
})
}
render() {
let editedSummary = this.state.summary.replace(/(<p>|<b>|<\/p>|<\/b>)/g, '')
let spiltGenre = this.state.genre.join(', ');
return(
<div>
<input
type="text"
ref="query"
onChange={this.updateSearchHandler}/>
<SearchResults
showTitle={this.state.title}
showSummary={editedSummary}
showRating={this.state.rating}
showImage={this.state.image}
showGenre={spiltGenre}/>
<AddButton
showTitle={this.state.title}
showGenre={spiltGenre}/>
</div>
)
}
}
export default Searchbar;
Upvotes: 1
Views: 14289
Reputation: 62773
You can use a ternary operator to test if response.data.image
is defined. If so, return response.data.image.medium
, if not return null
or another value. A ternary operator works like this:
const isTrue = true;
const newVariable = (isTrue ? 'Its true' : 'Its false');
If isTrue
is true
, then newVariable
is Its true
. If isTrue
is false
, then newVariable
is Its false
.
Here's a simplified example:
const response = {
data: {
name: "My Name",
summary: "My Summary",
rating: {
average: "My Average"
},
genres: "My genres"
}
}
const state = {
title: response.data.name,
summary: response.data.summary,
rating: response.data.rating.average,
image: response.data.image ? response.data.image.medium : "No image",
genre: response.data.genres,
};
console.log(state);
Here's another method using Object Destructuring. Destructuring allows us to create variables from the object property names, rename any if needed, and define default values in the case the property is undefined. To use this, we would destructure response.data
into the 5 properties we want:
name
to title
summary
as summary
rating.average
to rating
image.medium
to medium
, with a default value of null
genres
to genre
We then need to pass these new constants to the state object.
I've provided 2 examples to show how it would handle a response with and without an image. First a response with an image
property.
const response = {
data: {
name: "My Name",
summary: "My Summary",
rating: {
average: "My Average"
},
image: {
medium: "My image"
},
genres: "My genres"
}
};
const {
name: title,
summary,
rating: {average: rating},
image: {medium: image} = {medium: null},
genres: genre
} = response.data;
const newState = {
title,
summary,
rating,
image,
genre
}
console.log(newState);
And now a response without an image
property.
const response = {
data: {
name: "My Name",
summary: "My Summary",
rating: {
average: "My Average"
},
genres: "My genres"
}
}
const {
name: title,
summary,
rating: {average: rating},
image: {medium: image} = {medium: null},
genres: genre
} = response.data;
const newState = {
title,
summary,
rating,
image,
genre
}
console.log(newState);
Upvotes: 1
Reputation: 891
You can do if/else in the callback of axios.
I would do:
image: response.data.image != null ? response.data.image.medium: '' ,
Or with if/else:
let imageMedium = '';
if (response.data.image != null) {
imageMedium = response.data.image.meduim
}
Upvotes: 0