본문 바로가기

개발새발 개발자/ReactJS

[ReactJS] 4-3. Loading States

데이터가 나타나는 과정

: 데이터 없이 컴포넌트가 로딩 -> 데이터를 위해 API를 호출 -> API가 데이터 전송 -> 컴포넌트 state 업데이트

API 콜을 타임아웃 기능으로 유사하게 구현해보겠다.


1. 영화 리스트를 function으로 이동하기


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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import React, { Component } from "react"
import "./App.css"
import Movie from "./Movie" //Movie.js에서 여기로 export한 컴포넌트를 import
 
class App extends Component {
  /* componentWillMount(){
    console.log('will mount');
  }
  componentDidMount(){
    console.log('did mount');
   }  */
 
  state = {}
 
  componentDidMount() {
    //1000ms = 1sec
    setTimeout(() => {
      this.setState({
        movies: [
          {
            title: "Matrix",
            poster:
              "https://m.media-amazon.com/images/M/MV5BNzQzOTk3OTAtNDQ0Zi00ZTVkLWI0MTEtMDllZjNkYzNjNTc4L2ltYWdlXkEyXkFqcGdeQXVyNjU0OTQ0OTY@._V1_.jpg"
          },
          {
            title: "Full Metal Jacket",
            poster:
              "https://assets4.domestika.org/project-items/001/116/314/FULL_METAL_JACKET_2-big.jpg?1414517836"
          },
          {
            title: "Oldboy",
            poster: "https://images-na.ssl-images-amazon.com/images/I/41OAXAVK27L.jpg"
          },
          {
            title: "Star Wars",
            poster:
              "https://imgc.allpostersimages.com/img/posters/star-wars-the-force-awakens-one-sheet_u-L-F8G58H0.jpg?src=gp&w=300&h=375"
          },
          {
            title: "Trainspotting",
            poster:
              "https://static1.squarespace.com/static/588f754e5016e1c481e826a2/588f8787414fb54982bca29a/588f878e2e69cfbfa42cfcd9/1502120682677/Trainspotting+black.jpg?format=750w"
          }
        ]
      })
    }, 5000)
  }
 
  render() {
    return (
      <div className="App">
        {/* movie는 현 사이클의 현재 엘리먼트를 의미한다. 우리가 제공하는 리스트의 숫자는 index라고 부르자. */}
        {this.state.movies.map((movie, index) => {
          // 괄호 넣는 것 잊지 말기
          return <Movie title={movie.title} poster={movie.poster} key={index} /> //key prop으로 index를 작성
        })}
      </div>
    )
  }
}
 
export default App
 
cs

state에 있던 리스트를 setTimeout 함수 안으로 옮긴다. 이때 컴파일은 제대로 되지만 페이지를 열면 에러가 난다.


1
2
3
4
5
6
7
8
9
10
11
12
 render() {
    return (
      <div className="App">
        {/* movie는 현 사이클의 현재 엘리먼트를 의미한다. 우리가 제공하는 리스트의 숫자는 index라고 부르자. */}
        {this.state.movies.map((movie, index) => {
          // 괄호 넣는 것 잊지 말기
          return <Movie title={movie.title} poster={movie.poster} key={index} /> //key prop으로 index를 작성
        })}
      </div>
    )
  }
}
cs

map을 돌리려고 하는데 불러 올 state.movies가 없기 때문! (앞서 state에 있던 리스트를 옮겼으므로) 여기서 loading states가 필요하다.


2. loading states


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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import React, { Component } from "react"
import "./App.css"
import Movie from "./Movie" //Movie.js에서 여기로 export한 컴포넌트를 import
 
class App extends Component {
  /* componentWillMount(){
    console.log('will mount');
  }
  componentDidMount(){
    console.log('did mount');
   }  */
 
  state = {}
 
  componentDidMount() {
    //1000ms = 1sec
    setTimeout(() => {
      this.setState({
        movies: [
          {
            title: "Matrix",
            poster:
              "https://m.media-amazon.com/images/M/MV5BNzQzOTk3OTAtNDQ0Zi00ZTVkLWI0MTEtMDllZjNkYzNjNTc4L2ltYWdlXkEyXkFqcGdeQXVyNjU0OTQ0OTY@._V1_.jpg"
          },
          {
            title: "Full Metal Jacket",
            poster:
              "https://assets4.domestika.org/project-items/001/116/314/FULL_METAL_JACKET_2-big.jpg?1414517836"
          },
          {
            title: "Oldboy",
            poster: "https://images-na.ssl-images-amazon.com/images/I/41OAXAVK27L.jpg"
          },
          {
            title: "Star Wars",
            poster:
              "https://imgc.allpostersimages.com/img/posters/star-wars-the-force-awakens-one-sheet_u-L-F8G58H0.jpg?src=gp&w=300&h=375"
          },
          {
            title: "Trainspotting",
            poster:
              "https://static1.squarespace.com/static/588f754e5016e1c481e826a2/588f8787414fb54982bca29a/588f878e2e69cfbfa42cfcd9/1502120682677/Trainspotting+black.jpg?format=750w"
          }
        ]
      })
    }, 5000)
  }
 
  // 함수를 만들어 놓고
  _renderMovies = () => {
    const movies = this.state.movies.map((movie, index) => {
      // 괄호 넣는 것 잊지 말기
      return <Movie title={movie.title} poster={movie.poster} key={index} /> //key prop으로 index를 작성
    })
    return movies
  }
 
  // render에 조건문으로 집어넣기
  render() {
    return <div className="App">
    {this.state.movies ? this._renderMovies() : "Loading"}</div>
  }
}
 
export default App
 
cs

movies라는 variable에 데이터를 저장해서 데이터가 없다면 'Loading'을 띄우고, 있으면 영화정보가 보이도록 한다.


_renderMovies

언더바를 쓴 이유는, 리액트 자체 함수와 나만의 함수에 차이를 두기 위해서다. 내 함수는 언더바로 시작하도록!


= () =>

이건 최신 자바스크립트인데 풀스택 강의에서 자세히 다룰 것이라고 한다.


실행하면 Loading 글씨가 먼저 뜨고 5초 뒤 영화 리스트를 출력한다.


정리하면, 데이터가 있는지 없는지 물어보고 true면 영화 정보 출력, false면 "Loading"을 출력한다. true일 때 renderMovies를 실행하면 안에 있는 const movies 같은 variables를 출력한다. 해당 variables에는 매핑을 통해서 제목이랑 포스터가 보이게 설정되어 있다. 그리고 이 매핑 기능은 영화 리스트를 가져와서 출력한다. 


1
const movies = [<Movie props />,<Movie props />]
cs

movies를 출력할 때 이렇게 정렬된 항목(array)를 보여주는 것이다. 이 작업없이 state를 접근하려고 한다면, state에 내용이 없기 때문에 에러가 난다.