[React] Movie app clone coding : Loading States

4 minute read

4-3. Loading States

우리에게 필요한 데이터가 항상 즉시 존재하는 것은 아니다. 데이터 없이 component가 로딩하고, 데이터를 위해 API를 읽어오고, API가 데이터를 주면 component state를 업데이트 한다.

API calltimeout 기능으로 유사하게 구현해본다.

이를 위해, movie listfunction 으로 이동한다.

 1  state = {
 2   // 비워짐
 3  }
 4
 5  componentDidMount(){
 6    setTimeout(() => {
 7      this.setState({
 8        movies: [      // movie list를 여기로 이동
 9          {
10            title: "Matrix",
11            poster: "https://displate.com/displates/2016-09-30/60a3501bd3167cf9330acef43ab51ab3.jpg?w=280&h=392"
12          },
13          {
14            title: "Full Metal Jacket",
15            poster: "https://cf5.s3.souqcdn.com/item/2016/05/17/10/74/99/15/item_XL_10749915_14378548.jpg"
16          },
17          {
18            title: "Oldboy",
19            poster: "https://posterspy.com/wp-content/uploads/2016/02/Oldboy-by-Clay-Disarray-oct.jpg"
20          },
21          {
22            title: "Start Wars",
23            poster: "http://aidanmoher.com/blog/wp-content/uploads/2011/01/Olly-Moss-Star-Wars.jpeg"
24          },
25          {
26            title: "Trainspotting",
27            poster: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXZIzbi2UWobCwSZbNtYjdUNvyhhvTt4I9_-7Gf06ZXHdm0trT"
28          }
29        ]
30      })
31    }, 5000)       // 1000 = 1초
32  }

{this.state.movies.map((movie, index) 에서 map 을 실행하려는데 states.movies 가 사라졌으므로 에러가 발생한다. 아래와 같이 수정해준다.

 1// App.js
 2 ...
 3   render() {
 4    return (
 5      <div className="App">
 6        Loading       // 수정
 7      </div>
 8    );
 9  }
10  ...

영화가 state 에 없을 때는 Loading 을 띄우거나 영화 리스트 가 보이게 만든다.

영화 리스트를 불러올 function을 만든다. 아래와 같이 작성한다.

 1// App.js
 2    ...
 3    _renderMovies = () => {
 4    const movies = this.state.movies.map((movie, index) => {
 5      return <Movie title={movie.title} poster={movie.poster} key={index} />
 6    })
 7    return movies
 8  }
 9
10  render() {
11    return (
12      <div className="App">
13        {this.state.movies ? this._renderMovies() : 'Loading'}
14      </div>
15    );
16  }
17
18    ...

위 코드를 살펴보면 movies 라는 variable 에 데이터를 저장한다. : const movies =

데이터가 없을 때 loading 을 띄우고 있으면 영화정보가 보이게 한다. : {this.state.movies ? this._renderMovies() : 'Loading'}

_renderMovies() 에서 underscore _ 를 쓰는 이유는 리액트는 자체 기능이 많기 때문에 리액트 자체 기능과 개발자가 만든 기능에 차이를 두기 위해서이다.

정리

찾고 있는 데이터가 있는지 체크하고 자바스크립트에 물어본 후 true이면 영화 정보를 출력하고, 없으면 loading을 출력한다.

render movies 라는 기능을 실행할 때, 위와 같은 variables 를 출력할 것이다.

해당 variables 에는 mapping 을 통해서 제목, 포스터가 보이게 된다.

movies 를 출력할 때 정렬된 항목(array) 를 보여주는 것이다.

전체 코드

App.js

 1import React, { Component } from 'react';
 2import './App.css';
 3import Movie from './Movie';
 4
 5class App extends Component {
 6
 7  state = {
 8
 9  }
10
11  componentDidMount(){
12    setTimeout(() => {
13      this.setState({
14        movies: [
15          {
16            title: "Matrix",
17            poster: "https://displate.com/displates/2016-09-30/60a3501bd3167cf9330acef43ab51ab3.jpg?w=280&h=392"
18          },
19          {
20            title: "Full Metal Jacket",
21            poster: "https://cf5.s3.souqcdn.com/item/2016/05/17/10/74/99/15/item_XL_10749915_14378548.jpg"
22          },
23          {
24            title: "Oldboy",
25            poster: "https://posterspy.com/wp-content/uploads/2016/02/Oldboy-by-Clay-Disarray-oct.jpg"
26          },
27          {
28            title: "Start Wars",
29            poster: "http://aidanmoher.com/blog/wp-content/uploads/2011/01/Olly-Moss-Star-Wars.jpeg"
30          },
31          {
32            title: "Trainspotting",
33            poster: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXZIzbi2UWobCwSZbNtYjdUNvyhhvTt4I9_-7Gf06ZXHdm0trT"
34          }
35        ]
36      })
37    }, 1000)       // 1000 = 1초
38  }
39
40  _renderMovies = () => {
41    const movies = this.state.movies.map((movie, index) => {
42      return <Movie title={movie.title} poster={movie.poster} key={index} />
43    })
44    return movies
45  }
46
47  render() {
48    return (
49      <div className="App">
50        {this.state.movies ? this._renderMovies() : 'Loading'}
51      </div>
52    );
53  }
54}
55
56export default App;