Skip to content

Exercise 04 : Load and parse JSON and show loaded movies data

Introduction

This exercise teaches how to load JSON data and show loaded data in a React application. This movie example application will load data from the movie db.

Show a movies list: Image 01

Show a selected movie video: Image 02

The Movie DB

Note

Don't create any aws accounts/projects, just get your API key from your settings!

Sign up to The Movie DB and get the api key. Learn the basics of API and Getting Started.

You can find your API key from your profile/settings. An example request looks like this (replacing the api_key_here text with your own API key):

1
https://api.themoviedb.org/3/movie/76341?api_key=api_key_here

Example response will be returned with JSON data:

Image 03

For example, Now playing movies will be used in this tutorial with a following API call:

1
https://api.themoviedb.org/3/movie/now_playing?api_key=your_api_key

React project

Create a new React project and name it to movies-app.

1
npx create-react-app movies-app

Install and use Axios

Install Axios and use it to load JSON data in your application

1
npm install axios

MovieList component

Create a new MovieList component inside your App.js. This component will load and hold all the movies data. Now it only render p element with MovieList text.

1
2
3
4
5
function MovieList() {
  return(
    <p>MovieList</p>
  )
}

And remember use it in App.js.

1
2
3
4
5
6
7
function App() {
  return (
    <div className="App">
      <MovieList/>
    </div>
  );
}

Use React hooks to store loaded movies data in your MovieList component.

1
const [movies, setMovies] = useState([]) 

Load movies data with Axios and React effect hooks.

1
2
3
4
5
6
7
useEffect(() => {
  axios
    .get('https://api.themoviedb.org/3/movie/now_playing?api_key=your_api_key&append_to_response=videos')
    .then(response => {
      setMovies(response.data.results)
    })
}, [])

Note

Remember use your own API key in above request.

MovieListItem component

Create a new MovieListItem component inside your App.js. This component will render one movie data in the UI. Now it will only display movie title text.

1
2
3
4
5
function MovieListItem(props) {
  return(
    <p>{props.movie.original_title}</p>
  )
}

Modify MovieList component

Use MovieListItem component in MovieList component rendering. A map function loops through all the movies. Movie object will be send to MovieListItem component via props.

Now conditional rendering is done with movies array length. Loading, please wait... is displayed, when data is loading (if there aren't any movies inside a movies array). You should implement timeout to display for example Can't load movies text if data is not available.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if (movies.length === 0) {
  return(
    <div style={{flex: 1, padding: 20}}>
      <p>Loading, please wait...</p>
    </div>
  )
} else {
    const movieItems = movies.map((movie,index) =>
      <MovieListItem key={index} movie={movie}/>
    );

  return(
    <div style={{flex: 1, padding: 20}}>
      {movieItems}
    </div>
  )
}

Modify MovieListItem component

Modify MovieListItem component to display more data from the Movie. Check the Movie DB API, which data is available. Be innovative!

Image 04

Show more information

Now you are only using now_playing flag in request and it doesn't get movie detail information. You can query a more movie specfic data from the Movie DB with a below command

1
https://api.themoviedb.org/3/movie/movie_id?api_key=api_key_here&append_to_response=videos

Note

You need to specify correct movie_id and your own api_key_here.

Modify MovieListItem component to use Axios and load movie specific data with React Hooks effect.

1
2
3
4
5
6
7
8
9
const [movie, setMovie] = useState([])

useEffect(() => {
  axios
    .get('https://api.themoviedb.org/3/movie/'+props.movie.id+'?api_key=api_key_here&append_to_response=videos')
    .then(response => {
      setMovie(response.data)
    })
}, [])

You can display for example Movie poster, genres and video based data.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
let IMAGEPATH = 'http://image.tmdb.org/t/p/w500'
let imageurl = IMAGEPATH + props.movie.poster_path;

// get genres
var genres = "";  
if (movie !== undefined && movie.genres !== undefined) {
  for (var i=0;i<movie.genres.length;i++) {
    genres += movie.genres[i].name+" ";
  }
}

// get first youtube video
var video = "";
if (movie !== undefined && movie.videos !== undefined && movie.videos.results !== undefined) {
  video = <span style={{color:'blue', cursor:'pointer'}} onClick={() => videoPressed(movie.videos.results[0].key)}>{movie.videos.results[0].name}</span>
}

And use return to render some movie based data:

1
2
3
4
5
6
7
8
9
return(
    <div className="Movie">
      <img src={imageurl}/>
      <p className="MovieTitle">{props.movie.original_title} : {props.movie.release_date}</p>
      <p className="MovieText">{props.movie.overview}</p>
      <span className="GenresText">Genres: {genres}</span><br/>
      <span className="VideosText">Video: {video}</span>
    </div>
  )

You can create own styles or use below ones in App.css.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
img {
  width: 100px;
  float: left;
  padding-right: 5px;
}

.Movie {
  width: 600px;
  height: 150px;
  float: left;
  margin: 5px;
}

.MovieTitle {
  font-weight: bold;
}

.MovieText {
  font-size: 70%;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3; /* number of lines to show */
  -webkit-box-orient: vertical;
}

.GenresText, .VideosText {
  font-size: 70%;
}

.VideoText {
  color:'blue';
  cursor: pointer;
}

Try to use react-modal and react-youtube npm packages. Open a modal and show a selected movie video. You might need to pass selected video id to parent component via props (it depends which component is opening a modal window).

Image 06

Push exercise 04 / Movies to GitLab

Test your application in web browser, take screenshots and commit/push your project and screenshots back to JAMKIT/GitLab. Remember move your exercise/issue ticket from Doing to In Review in Issues Board and write your learning comments to issue comments.

Save screenshots to movies-app folder.