본문 바로가기

Information Technology

[React] 리액트 시작하고 사용해보기

1. 리액트 설치

Git hub에서 사용할 README

 

 

대략적으로 작동하는 JSON

2. 컴포넌트의 구조

class Movie extends Component{  // Component 클래스 상속

    static propTypes = {    // 부모 컴포넌트로부터 받는 값의 타입을 판단 가능
        title: PropTypes.string.isRequired, // 필수로 받아야하는 값. 있는지 없는지 확인 가능
        poster: PropTypes.string
    }

    render(){
        return(
            <div>
                <MoviePoster poster = {this.props.poster}/>	// 자식 Component의 props 생성
                <h1>{this.props.title}</h1>
            </div>
            
        )
    }
}
// 부모 -> 자식으로 props를 내려줌. props를 이용해 정보 출력
class MoviePoster extends Component{

    static propTypes = {
        poster: PropTypes.string.isRequired
    }
    render(){
        return(
            <img src={this.props.poster}></img>
        )
    }
}

export default Movie

컴포넌트는 부모 컴포넌트가 자식 컴포넌트를 안에 품는 구조를 취한다.

 

자식 컴포넌트는 부모 컴포넌트로부터 데이터를 전달받고, props라는 객체에 이를 저장한다.

 

리액트에서 사용되는 클래스들은 모두 Component 클래스를 상속extends 한다.

 

3. 리액트 문법

리액트의 동작은 { } 괄호 안에서 진행된다.


1. setState

  // Render: componentWillMount -> render -> comonentDidMount
  // Update: componentWillRecieveProps -> 이전 props와 새로운 props가 다르면 shouldComponentUpdate==true : 업데이트 실행 -> componentWillUpdate -> render -> componentDidupdate
  // Component 내부의 state가 바뀔 때마다 render 발생
  componentWillMount(){
  }

      // this.state.greeting = 'Something' 이와 같이 state를 직접 다루면 Render 과정이 작동하지 않음

  componentDidMount(){
    setTimeout(()=>{
      this.setState({
        movies: [
          {
            title: "Gravity",
            poster: "http://pds27.egloos.com/pds/201309/10/74/d0014374_522eb4d841703.jpg"
          },
          ...this.state.movies // 이전 영화 리스트는 그대로 둠(전부 가져옴)
        ]
      })
    },2000)
  }

state를 변경할 땐 componentDidMount()에서 state를 직접 호출해 변경하지 않는다. 그렇게 하면 render()가 동작하지 않는다.

대신 this.setState()를 통해 state를 변경한다.


2. setState + 삼항조건문

 componentDidMount(){
    setTimeout(()=>{
      this.setState({
        movies: [
          {
            title: "Starwars",
            poster: "http://www.cine-rewind.com/imgdata/cine-rewind_com/201909/2019090412212220.jpg"
          },
          {
            title: "Avengers",
            poster: "http://mblogthumb1.phinf.naver.net/MjAxOTA0MjhfMjIz/MDAxNTU2MzgzMzM0OTQ4.QsFUA378VIEcCK9dT5eBQPIDxw9u2F1sQHqWEL_i-x4g.vBPx-eDSF-mtIoUFKRg8Dx9JKwJIU1O5tPwOinL2QGIg.JPEG.kimdala/%EC%96%B4%EB%B2%A4%EC%A0%B8%EC%8A%A4_%EC%97%94%EB%93%9C%EA%B2%8C%EC%9E%84_(3).jpg?type=w800"
          },
          {
            title: "Parasite",
            poster:"https://pds.joins.com/news/component/htmlphoto_mmdata/201905/26/8ea065cf-5019-4de4-ab38-026b15a67e52.jpg"
          },
          {
            title: "Joker",
            poster: "https://img.hankyung.com/photo/201909/2019090510321912061-540x800.jpg" 
          }
        ],
      })
    },2000)
  }

  state = { // 처음엔 state에 movies 존재 x
  }

  _renderMovies = ()=>{ // 리액트 자체 기능과 사용자 정의 기능 간의 구분을 위해
    const movies = this.state.movies.map((movie, index)=>{  // 매핑을 통해. moive -> movies의 각 객체
      return <Movie title={movie.title} poster={movie.poster} key={index}/> // movies[0]의 title과 poster를 Moive 컴포넌트의 prpos에 전달. key값을 가져야 함
    })
    return movies
  }

  render() {
    return (
      <div className="App">
        {this.state.movies ? this._renderMovies() : 'Loading'}
      </div>
    );
  }
}

1. render()에서 삼항 조건문 실행

2. state에 movies 객체 존재하지 않음

3. 'Loading' 출력

4. render가 끝났으니 componentDidMount() 실행

5. componentDidMount()에서 setState를 통해 2초가 지나면 state에 movies 객체를 추가

6. 다시 render() 실행되고 이번 삼항조건문 실행

7. 5번은 통해 이번엔 state에 movies 객체 존재

8. _renderMovies() 실행

9. 영화 목록 출력


3. Smart component v. Dumb component

 

// 1.Smart
class MoviePoster extends Component{

    static propTypes = {
        poster: PropTypes.string.isRequired
    }
    render(){
        return(
            <img src={this.props.poster}></img>
        )
    }
}

// 2.Dumb
function MoviePoster({poster}){
    return (
        <img src={poster}></img>
    )
}

//1번과 2번 모두 동일한 기능

· 클래스 형태의 Component -> Smart component. State 존재

 

· 함수 형태의 Component -> Functional component. 오직 return을 위해 존재. props로 사용할 변수를 함수의 매개변수로 받음. function render, 라이프 사이클 필요 x. State 존재 x

MoviePoster.propTypes = {
    poster: PropTypes.number.isRequired
}

functional component 역시 propTypes 확인 가능

propType 에러 발생 확인

import React from 'react';
import PropTypes from 'prop-types';
import './Movie.css';

function Movie({title, poster}){	// props로 사용할 매개변수들
    return(
        <div>
            <MoviePoster poster = {poster}/>	// 더이상 클래스가 아니기 때문에 this 필요x
            <h1>{title}</h1>
        </div>
    )
}

4. AJAX로 URL 불러오기

  componentDidMount(){ // DidMount를 통해 해당 URL 주소를 fetch(잡아채옴)
    fetch("https://yts.lt/api/v2/list_movies.json?sort_by=rating")
  }

Ajax를 통해 URL에 저장된 데이터들을 비동기화(Asynchronous) 방식으로 가져올 수 있음

fetch를 통해 movies.json 파일 호출


5. Promise

  componentDidMount(){ // DidMount를 통해 해당 URL 주소를 fetch(잡아채옴)
    fetch('https://yts.lt/api/v2/list_movies.json?sort_by=rating')
    console.log('Hello') // 첫 번째 줄(fetch)가 실행되지 않으면 두 번째 줄 실행x -> synchronous
  }

- 동기화 작업(Synchronous): 라인이 순서대로 실행됨. 위 예제에서는 fetch가 실행되지 않으면 console.log()는 계속 대기

- 비동기화 작업(Asynchronous): 라인들이 각각 실행. 순서에 큰 제약 x. 이걸 가능하게 해주는 게 Promise 

 

  componentDidMount(){ // DidMount를 통해 해당 URL 주소를 fetch(잡아채옴)
    fetch('https://yts.lt/api/v2/list_movies.json?sort_by=rating')
    .then(response => console.log(response)) // 위의 작업이 끝나면 then 호출. then은 fetch의 response를 받음
    .catch(err => console.log(err)) // 위의 라인들에서 에러가 나면 이걸 catch해서 에러처리
  }

. then에서는 이전 라인의 작업이 이뤄지면 지정된 역할 실행

.then 뒤에 또 다른. then을 추가할 수 있음

마지막에. catch를 통해 예외처리 실행

 

- status: 200 -> 작업이 성공적으로 이뤄짐

- bodyUsed: false -> 아직 가져온 URL의 body를 사용하지 않았음

  componentDidMount(){ // DidMount를 통해 해당 URL 주소를 fetch(잡아채옴)
    fetch('https://yts.lt/api/v2/list_movies.json?sort_by=rating')
    .then(response => response.json()) // fetch에서 가져온 URL을 json으로 변환
    .then(json => console.log(json)) // json을 console.log()로 출력
    .catch(err => console.log(err)) // 위의 라인들에서 에러가 나면 이걸 catch해서 에러처리
  }


6. Async Await

_getMovies = async () =>{ // await 속성의 _getMovies 함수
  const movies = await this._callApi() // movies 변수는 this._callApi()가 끝날 때 까지 기다려서 callApi의 return값 저장. 이게 await   
  this.setState({ // 위에서 호출된 _callApi의 실행이 마무리되기 전까지는 실행x. 
    movies // _callApi()의 리턴값을 state에 저장
  })
}

_callApi = ()=>{
  return fetch('https://yts.lt/api/v2/list_movies.json?sort_by=like_count')
  .then(response => response.json()) // fetch에서 가져온 값
  .then(json => json.data.movies) // arrow function : return 기능 내재. json.data.movies를 리턴
  .catch(err => console.log(err))
}

await: 함수의 속성. await 선언이 된 함수가 작업을 완료할 때까지 기다림. 작업이 성공적일 필요는 x, 오직 작업이 완료되기만 하면 됨. await 함수가 마무리되지 않으면 다음 라인은 실행 x

* arrow function  ( )=> { } : 자동으로 return 기능을 가지고 있음.

이전에 설정한 poster props가 존재하지 않으므로 에러 발생

  _renderMovies = ()=>{ // 리액트 자체 기능과 사용자 정의 기능 간의 구분을 위해
    const movies = this.state.movies.map((movie, index)=>{
      console.log(movie)
      // 매핑을 통해. moive -> movies의 각 객체
      return <Movie title={movie.title} poster={movie.large_cover_image} key={index}/> // movies[0]의 title과 poster를 Moive 컴포넌트의 prpos에 전달. key값을 가져야 함
    })
    return movies
  }

_renderMovies에서 전달해주는 movie의 props을 변경

 

'Information Technology' 카테고리의 다른 글

[Python] 간단한 소켓 프로그래밍  (1) 2020.03.24
[JAVA 기초] Static과 Public  (0) 2020.01.16
[React Native] Weather APP  (0) 2020.01.14