I am building a simple movie catalogue using themoviedb API however I am facing an issue that I am unable to solve. The issue is that the result after fetching is always undefined.
I tried with the method ponentWillMount to fetching data and the setting the state inside this method but it does not work. I tried to fetch inside constructor, no result.
This is my code so far
import React, { Component } from 'react';
import Header from './ponents/Header';
import MovieList from './ponents/MovieList';
import Footer from './ponents/Footer';
const MOVIE_API = ";language=en-US&sort_by=release_date.desc&include_adult=true&include_video=false&page=2&primary_release_year=2018";
//class
class App extends Component {
constructor(props){
super(props);
this.state = {
movies: [],
movieName: ''
}
}
ponentWillMount(){
this.fetchMovie();
}
//fetching movie
fetchMovie = () =>{
const req = new Request(MOVIE_API, {
method: 'GET',
cache: 'default'
});
fetch(req).then(response =>{
return response.json();
}).then(data =>{
console.log(data); //REF 1;
this.setState({
movies: data
});
}).catch(err => {
console.log("ERROR: " + err);
})
}
render() {
return (
<div className="root">
<Header />
<MovieList moviesRes={this.state.movies}/>
<Footer />
</div>
);
}
}
export default App;
As you can see I called the method ponentWillMount to fetch the data but it does not work. It is also noticeable that if I log the data (REF 1) I can see the result (json).
===========================
EDIT
This is the code for MovieList
/*import React, { Component } from 'react';
export default class MovieList extends Component{
constructor(props){
super(props);
this.state = {
movies: this.props.movieRes
}
}
render(){
//if result is undefined
if(this.state.movieRes === undefined){
return(
<h1>Loading...</h1>
);
}else{
return(
<ul>
{this.state.movieRes.map((movie, index)=>{
return (
<li key={index}>{movie.title}</li>
);
})}
</ul>
);
}
}
}*/
=================
update child code
import React, { Component } from 'react';
export default class MovieList extends Component{
render(){
const { movieRes = [] } = this.props; // we are assigning a default prop here of an empty array.
return(
<ul>
{
//return movie from array
movieRes.map((movie, index)=>{
return (
<li key={index}>
{movie.id}
</li>
);
})
}
</ul>
);
}
}
In this I way I suppress the error, but still it is not working. From what I learnt, React should render as soon as it detect changes but for some reason it not the case.
IMAGE
As you can see from the image when I am passing the array from parent ponent to the child ponent the array length is 20 but in the child ponent the array length seems to be 0
===================
Solution
I changed the ponent from class to a const and pass to it the array and everything went smooth. Here is the final code:
import React from 'react';
const MovieList = ({movies}) =>{
if(!movies){
return <h1>Loading...</h1>
}
return (
<ul>
{
movies.map((movie, index) => {
return (
<li key={index}>
<p>{movie.title}</p>
</li>
)
})
}
</ul>
);
}
export default MovieList;
I am building a simple movie catalogue using themoviedb API however I am facing an issue that I am unable to solve. The issue is that the result after fetching is always undefined.
I tried with the method ponentWillMount to fetching data and the setting the state inside this method but it does not work. I tried to fetch inside constructor, no result.
This is my code so far
import React, { Component } from 'react';
import Header from './ponents/Header';
import MovieList from './ponents/MovieList';
import Footer from './ponents/Footer';
const MOVIE_API = "http://api.themoviedb/3/discover/movie?api_key=72049b7019c79f226fad8eec6e1ee889&language=en-US&sort_by=release_date.desc&include_adult=true&include_video=false&page=2&primary_release_year=2018";
//class
class App extends Component {
constructor(props){
super(props);
this.state = {
movies: [],
movieName: ''
}
}
ponentWillMount(){
this.fetchMovie();
}
//fetching movie
fetchMovie = () =>{
const req = new Request(MOVIE_API, {
method: 'GET',
cache: 'default'
});
fetch(req).then(response =>{
return response.json();
}).then(data =>{
console.log(data); //REF 1;
this.setState({
movies: data
});
}).catch(err => {
console.log("ERROR: " + err);
})
}
render() {
return (
<div className="root">
<Header />
<MovieList moviesRes={this.state.movies}/>
<Footer />
</div>
);
}
}
export default App;
As you can see I called the method ponentWillMount to fetch the data but it does not work. It is also noticeable that if I log the data (REF 1) I can see the result (json).
===========================
EDIT
This is the code for MovieList
/*import React, { Component } from 'react';
export default class MovieList extends Component{
constructor(props){
super(props);
this.state = {
movies: this.props.movieRes
}
}
render(){
//if result is undefined
if(this.state.movieRes === undefined){
return(
<h1>Loading...</h1>
);
}else{
return(
<ul>
{this.state.movieRes.map((movie, index)=>{
return (
<li key={index}>{movie.title}</li>
);
})}
</ul>
);
}
}
}*/
=================
update child code
import React, { Component } from 'react';
export default class MovieList extends Component{
render(){
const { movieRes = [] } = this.props; // we are assigning a default prop here of an empty array.
return(
<ul>
{
//return movie from array
movieRes.map((movie, index)=>{
return (
<li key={index}>
{movie.id}
</li>
);
})
}
</ul>
);
}
}
In this I way I suppress the error, but still it is not working. From what I learnt, React should render as soon as it detect changes but for some reason it not the case.
IMAGE
As you can see from the image when I am passing the array from parent ponent to the child ponent the array length is 20 but in the child ponent the array length seems to be 0
===================
Solution
I changed the ponent from class to a const and pass to it the array and everything went smooth. Here is the final code:
import React from 'react';
const MovieList = ({movies}) =>{
if(!movies){
return <h1>Loading...</h1>
}
return (
<ul>
{
movies.map((movie, index) => {
return (
<li key={index}>
<p>{movie.title}</p>
</li>
)
})
}
</ul>
);
}
export default MovieList;
Share
edited Jan 28, 2018 at 1:05
tufailra97
asked Jan 27, 2018 at 20:59
tufailra97tufailra97
571 gold badge1 silver badge7 bronze badges
5
- 1 Can you please give us the error you get? It would also help if you'll show us how the response is structured like. – Tamir Kfir Commented Jan 27, 2018 at 21:04
- Apologise, I do not get any error. It is the variable movies that does not get any value even after fetching data it keeps an empty array. – tufailra97 Commented Jan 27, 2018 at 21:12
-
Are you sure your response is an array? Maybe the response is structured like
{movies: []}
and then you have to getdata.movies
. – Tamir Kfir Commented Jan 27, 2018 at 21:17 - Whoa why are you putting movieRes in state? Just read it from props. That's your problem. It gets set in the state when it's empty during the constructor and nothing updates it. You don't need to copy stuff from props to state. Just read it from this.state in the render method. – stone Commented Jan 27, 2018 at 23:10
- Did as you said but it does not work, with the conditional render I do not get the result, without the conditional render I get error – tufailra97 Commented Jan 27, 2018 at 23:19
1 Answer
Reset to default 6Originally I misunderstood your issue but after re-reading it I noticed that you defined movies as an array in your constructor.
Without an actual error message, I'm going to assume that MovieList is expecting an array for it's prop movieRes and you're probably then trying to do something like .map
or a loop to render the movies.
However, the API you're using doesn't return an array. It returns an object with an array key'd under results
. So, I changed it to access data.results
when doing setState.
//fetching movie
fetchMovie = () =>{
const req = new Request(MOVIE_API, {
method: 'GET',
cache: 'default'
});
fetch(req).then(response =>{
return response.json();
}).then(data =>{
console.log(data);
this.setState({
movies: data.results // <-- change made here.
});
}).catch(err => {
console.log("ERROR: " + err);
})
}
Here's a working JSFiddle:
https://jsfiddle/patrickgordon/69z2wepo/99513/
EDIT: In the child ponent, instead of assigning props to state, just use props and default props.
import React, { Component } from 'react';
export default class MovieList extends Component{
render(){
const { movieRes = [] } = this.props; // we are assigning a default prop here of an empty array.
return(
<ul>
{movieRes.map((movie, index)=>{
return (
<li key={index}>{movie.title}</li>
);
})}
</ul>
);
}
}