Reputation: 1
I tried to call some rest API, but I got some issue.
Uncaught TypeError: Cannot read property 'name' of undefined
So here's my code:
class MovieDetailViewer extends React.Component {
constructor() {
super();
this.state = {
movieResponse: {}, // wont work
movieResponse: {
"id": 1,
"barcode": "000-000-003",
"name": "Django Unchained",
"fsk": "FSK_18",
"lend": false,
"deleted": false,
"genre": {
"id": 1,
"name": "Western"
},
"source": {
"id": 1,
"name": "Blu-Ray"
}
} // will work
}
componentDidMount() {
fetch('apiurltogetmovie')
.then((response) = > response.json())
.then(responseJson = > {
this.setState({ movieJsonResponse: responseJson.movie });
});
}
render() {
return (
<div>
<MovieDetails
movie={this.state.movieJsonResponse}
/>
</div>
);
}
}
class MovieDetails extends React.Component {
render() {
const movie = this.props.movie;
return (
<div>
<h1>{movie.name}</h1>
<h2>{movie.gerne.name} - {movie.source.name}</h2>
<p>
{movie.comment}
</p>
</div>
)
}
}
It looked like there was a problem with JSON response but if initialize movieResponse
with some default JSON it works.
At google I cant find any react example where the state is initialize with some value. Whats the best practice here?
So I am not sure why gerne.name
is undefinied
. If I log the JSON response to console it will be fine.
Upvotes: 0
Views: 79
Reputation: 445
Best practices that can be used here:
movie && movie.name.
{ movie && movie.name && <h1>{movie.name}</h1>}
Upvotes: 0
Reputation: 4911
The problem is that before the API call in MovieDetailViewer
finishes, MovieDetails
is rendered. But, since the response is not available, movieResponse
is still equal the initial value, which in this case is an empty object. Thus, when attempting to access movie.genre.name
, since movie
is empty, genre
will be undefined and name
unable to be accessed. To fix this, you should only render MovieDetails
once the response is available:
class MovieDetailViewer extends React.Component {
constructor() {
super();
this.state = {
movieResponse: null
}
}
...
render() {
return (this.state.movieJsonResponse) ? (
<div>
<MovieDetails movie={this.state.movieJsonResponse} />
</div>
) : (
<div className="loader">loading...</div>
);
}
}
It is worth noting that your check should likely be more thorough than this, and involve another property on the state describing the current status of the query (querying, success, error, etc.)
Upvotes: 2