'코딩 연습/React'에 해당되는 글 3건

Component State컴포넌트 안에서 쓸 수 있는 객체이다.

그리고 this.setState()를 활용하여 리액트만의 장점을 확인해보자



import React, { Component } from 'react';
import './App.css';
// Movie.js에서 Movie 클래스를 가져온다
import Movie from './Movie'

// extends를 사용하여 Component를 가져와야 App 이름의 컴포넌트를 만들 수 있다
class App extends Component {

  // state는 컴포넌트 안에서 사용되는 객체
  // 특징은 state가 바뀔 때마다 render()가 실행된다

  state = {
    movies: [
      {
        title: "Matrix",
        poster: "https://cdn.vox-cdn.com/thumbor/veUKpCnSKflt86VfCpTfyUqEfYQ=/0x0:1280x720/1200x800/filters:focal(538x258:742x462)/cdn.vox-cdn.com/uploads/chorus_image/image/52198011/c6f5a81cb0fcc1c0e5ae3cba9cc4f40ae35476cb.0.jpeg",
      },
      {
        title: "Oldboy",
        poster: "https://static01.nyt.com/images/2018/10/18/arts/18terracehouse/18terracehouse-articleLarge.jpg?quality=75&auto=webp&disable=upscale",
      },
      {
        title: "Terrace House",
        poster: "https://cdn.vox-cdn.com/thumbor/GltBWgYa-A_SKHFx2CKHEr93Zvw=/0x0:5760x3840/1200x0/filters:focal(0x0:5760x3840):no_upscale()/cdn.vox-cdn.com/uploads/chorus_asset/file/9898277/_DSC_I1A7700.JPG",
      },
      {
        title: "Suits",
        poster: "https://i.ytimg.com/vi/4qBl7_t0M_U/maxresdefault.jpg",
      },
      {
        title: 'Heart Signal',
        poster: 'https://t1.daumcdn.net/cfile/tistory/2165C83C58A206D523',
      }
    ]
  }



App 컴포넌트 밖에 있던 movies 객체를 컴포넌트 안에 위치한 state에 담았다.


  • state는 컴포넌트 안에서만 쓸 수 있는 객체이다.

  • 특이점은 함수를 통해 state에 담긴 값이 변경될 경우 자동으로 render() 메소드를 재실행시킨다.


// 컴포넌트가 마운트(트리에 삽입되면)되면 작동하는 메소드
  // state 값을 설정하면 render를 재실행한다
  componentDidMount(){
    // ()는 function()과 같은 의미
    setTimeout(() => {
      this.setState({
        movies: [
          // state 객체에서 영화정보가 담긴 movies 값을 불러온다
          ...this.state.movies,

          // 새로 추가할 데이터를 입력한다
          {
            title: 'Heart Signal',
            poster: 'https://t1.daumcdn.net/cfile/tistory/2165C83C58A206D523',
          }
      })
    }, 5000)
  }



마운트 후 componentDidMount() 메소드가 호출된다.


  • setTimeout()this.setState() 원하는 시간(5000=5초)이 지나서 호출되도록 하기 위함이다.
  • () => {}function(){}과 동일한 내용이다.
  • ...this.state.movies를 기존 데이터인 moives를 전부 읽어오는 것이다.
  • 따라서 기존 데이터에 새로운 영화 데이터를 추가 입력하여 state 값에 변화를 주었다.   



  render() {
    return (
<div className="App">
        {/* 리스트에 map 메소드를 사용하여 각 객체의 데이터를 컴포넌트로 전달 */}
        {/* index는 각 객체에 id 값을 넣어주며 key값으로 전달한다 */}
        {this.state.movies.map((movie, index) => {
          return <Movie title={movie.title} poster={movie.poster} key={index}/>
        })}
      </div>
    );
  }
}

export default App;



state의 값이 변화가 되면서 render() 메소드는 재실행된다.


  • state에 추가로 저장된 movies 데이터를 Movie 컴포넌트로 전달하여 기존 영화정보에서 5초 후 더 늘어난 영화 정보가 노출된다.




삼항연산자를 활용하여 리액트만의 극적인 효과 나타내기

동시에 나만의 메소드 만들기



class App extends Component {

  state = {
  }

  componentDidMount(){
    setTimeout(() => {
      this.setState({
        movies: [
          {
            title: "Matrix",
            poster: "https://cdn.vox-cdn.com/thumbor/veUKpCnSKflt86VfCpTfyUqEfYQ=/0x0:1280x720/1200x800/filters:focal(538x258:742x462)/cdn.vox-cdn.com/uploads/chorus_image/image/52198011/c6f5a81cb0fcc1c0e5ae3cba9cc4f40ae35476cb.0.jpeg",
          },
          {
            title: "Oldboy",
            poster: "https://static01.nyt.com/images/2018/10/18/arts/18terracehouse/18terracehouse-articleLarge.jpg?quality=75&auto=webp&disable=upscale",
          },
          {
            title: "Terrace House",
            poster: "https://cdn.vox-cdn.com/thumbor/GltBWgYa-A_SKHFx2CKHEr93Zvw=/0x0:5760x3840/1200x0/filters:focal(0x0:5760x3840):no_upscale()/cdn.vox-cdn.com/uploads/chorus_asset/file/9898277/_DSC_I1A7700.JPG",
          },
          {
            title: "Suits",
            poster: "https://i.ytimg.com/vi/4qBl7_t0M_U/maxresdefault.jpg",
          },
          {
            title: 'Heart Signal',
            poster: 'https://t1.daumcdn.net/cfile/tistory/2165C83C58A206D523',
          }
        ]
      })
    }, 5000)
  }



state에 작성했던 movies 값을 비워두자


  • this.setState()movies 값을 그대로 가져온다.



  // _(언더바)를 사용해 나만의 메소드와 리액트 자체 메소드에 구분을 주었다.
  // state에서 movies 값을 map() 메소드에 적용하여 새로운 배열을 만들어 movies 객체에 담아서 반환
  _renderMovies = () => {
    const movies = this.state.movies.map((movie, index) => {
      return <Movie title={movie.title} poster={movie.poster} key={index}/>
    })
    return movies
  }



render() 메소드 안에 작성했던 map() 메소드를 가져온다


  • _renderMovies는 나만의 메소드이므로 리액트 자체 메소드와 구분 짓기 위해 _(언더바)를 사용한다.
  • map()을 통해 만들어진 배열을 새로이 movies 변수에 담아서 반환한다.



  render() {
    return (
      <div className="App">
        {/* 삼항연산자 사용 */}
        {/* 컴포넌트 state에서 movies 값이 있다면 _renderMovies()를 실행하고 없으면 'Loading' 문자 출력 */}
        {this.state.movies ? this._renderMovies() : 'Loading'}
      </div>
    );
  }
}

export default App;



항연산자를 사용하여 state에서 movies 객체의 존재에 따라 데이터 출력을 달리한다.


  • statemovies 객체가 존재하면 _renderMovies()를 실행하여 영화 정보가 출력되도록 한다.
  • statemovies 객체가 없다면 'Loading' 문자만 웹브라우저에 노출된다.
  • 따라서 state에서 아무런 값이 없는 상태로 마운트된 후 5초가 지나서 componentDidMount()가 실행되어 statemovies 객체가 삽입된다.
  • state에 값에 변화가 생기면서 render()를 재실행한 후 _renderMovies()를 통해 Movie 컴포넌트에 영화 정보를 전달하여 웹브라우저에 노출시킨다.

 

'코딩 연습 > React' 카테고리의 다른 글

PropTypes로 데이터 형태 확인하기  (0) 2019.01.07
Array.prototype.map() 활용하기  (0) 2019.01.07
블로그 이미지

쵸잇

,

PropTypes으로 데이터 형태 확인하기

데이터 형태 확인을 통해 많은 버그를 잡을 수 있다. 우선 객체내 각 요소에 부합하는 propTypes를 할당한다 



import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './Movie.css';

class Movie extends Component {

    // 부모 컴포넌트에서 받은 데이터 형태를 규정하여 이와 다를 경우 에러가 발생한다
    static propTypes = {
        // isRequired는 필수사항으로 지정해준다. 부모컴포넌트에서 값이 없을 경우 오류발생
        title: PropTypes.string.isRequired,
        poster: PropTypes.string,
    }

    render() {
        return(
            <div>
                {/* MoviePoster 컴포넌트에 poster 값을 담아준다 */}
                <MoviePoster poster={this.props.poster} />
                {/* 부모컴포넌트에서 전달 받은 title 값을 출력한다 */}
                <h1>{this.props.title}</h1>
            </div>
        )
    }
}

class MoviePoster extends Component {
   
    // 부모 컴포넌트에서 받은 데이터를 체크하고, 지정한 타입과 다르면 에러 발생
    static propTypes = {
        poster: PropTypes.string.isRequired,
    }

    render() {
        return(
            // 부모컴포넌트인 Movie 컴포넌트에서 전달 받은 poster 값을 출력한다
            <img src={this.props.poster} />
        )
    }
}

export default Movie



객체내 각 요소에 PropTypes를 규정하면 데이터 형태를 확인한 후에 다음 단계로 넘어간다


  • PropTypes에는 string, number, bool, func 등 여러 타입을 사용할 수 있다.
  • isRequired를 사용하게 되면 해당 요소가 존재하지 않을시 에러를 발생시킨다. 따라서 반드시 요소 값을 입력해야한다.
  • PropTypes를 확인하고 유효한 경우에만 this.props.poster로 값이 전달된다.


'코딩 연습 > React' 카테고리의 다른 글

Component State with this.setState()  (0) 2019.01.10
Array.prototype.map() 활용하기  (0) 2019.01.07
블로그 이미지

쵸잇

,

map() 메소드를 활용하여 각 배열의 값을 일일이 컴포넌트에 전달하도록 코드를 작성하는 번거로움을 줄여보자



import React, { Component } from 'react';
import './App.css';
// Movie.js에서 Movie 클래스를 가져온다
import Movie from './Movie'

const movieTitles = [
  "Matrix",
  "Oldboy",
  "Terrace House",
  "Suits",
]

const movieImages = [
  "https://cdn.vox-cdn.com/thumbor/veUKpCnSKflt86VfCpTfyUqEfYQ=/0x0:1280x720/1200x800/filters:focal(538x258:742x462)/cdn.vox-cdn.com/uploads/chorus_image/image/52198011/c6f5a81cb0fcc1c0e5ae3cba9cc4f40ae35476cb.0.jpeg",
  "https://static01.nyt.com/images/2018/10/18/arts/18terracehouse/18terracehouse-articleLarge.jpg?quality=75&auto=webp&disable=upscale",
  "https://cdn.vox-cdn.com/thumbor/GltBWgYa-A_SKHFx2CKHEr93Zvw=/0x0:5760x3840/1200x0/filters:focal(0x0:5760x3840):no_upscale()/cdn.vox-cdn.com/uploads/chorus_asset/file/9898277/_DSC_I1A7700.JPG",
  "https://i.ytimg.com/vi/4qBl7_t0M_U/maxresdefault.jpg",
]


// extends를 사용하여 Component를 가져와야 App 이름의 컴포넌트를 만들 수 있다
class App extends Component {
  render() {
    return (
      <div className="App">
        {/* Movie 컴포넌트에 title, poster 값을 각각 담아준다 */}
        <Movie title={movieTitles[0]} poster={movieImages[0]} />
        <Movie title={movieTitles[1]} poster={movieImages[1]} />
        <Movie title={movieTitles[2]} poster={movieImages[2]} />
        <Movie title={movieTitles[3]} poster={movieImages[3]} />
      </div>
    );
  }
}

export default App;




배열의 요소가 늘어날수록 그만큼 컴포넌트에 전달하는 데이터가 늘어 코드량이 늘어난다.


  • movieTitles, movieImages 변수를 movies로 통합하여 객체 형태로 2개의 데이터를 담아 배열에 담는다.
  • map() 메소드를 활용하여 반복적인 코드를 줄인다.




import React, { Component } from 'react';
import './App.css';
// Movie.js에서 Movie 클래스를 가져온다
import Movie from './Movie'

const movies = [
  {
    title: "Matrix",
    poster: "https://cdn.vox-cdn.com/thumbor/veUKpCnSKflt86VfCpTfyUqEfYQ=/0x0:1280x720/1200x800/filters:focal(538x258:742x462)/cdn.vox-cdn.com/uploads/chorus_image/image/52198011/c6f5a81cb0fcc1c0e5ae3cba9cc4f40ae35476cb.0.jpeg",
  },
  {
    title: "Oldboy",
    poster: "https://static01.nyt.com/images/2018/10/18/arts/18terracehouse/18terracehouse-articleLarge.jpg?quality=75&auto=webp&disable=upscale",
  },
  {
    title: "Terrace House",
    poster: "https://cdn.vox-cdn.com/thumbor/GltBWgYa-A_SKHFx2CKHEr93Zvw=/0x0:5760x3840/1200x0/filters:focal(0x0:5760x3840):no_upscale()/cdn.vox-cdn.com/uploads/chorus_asset/file/9898277/_DSC_I1A7700.JPG",
  },
  {
    title: "Suits",
    poster: "https://i.ytimg.com/vi/4qBl7_t0M_U/maxresdefault.jpg",
  }
]

// extends를 사용하여 Component를 가져와야 App 이름의 컴포넌트를 만들 수 있다
class App extends Component {
  render() {
    return (
      <div className="App">
        {/* movies 배열에 map() 메소드를 사용하여 각 객체의 데이터를 컴포넌트로 전달 */}
        {/* index는 각 객체에 id 값을 넣어주며 key값으로 전달한다 */}
        {movies.map((movie, index) => {
          return <Movie title={movie.title} poster={movie.poster} key={index}/>
        })}
      </div>
    );
  }
}

export default App;


 

map() 메소드는 배열의 모든 요소에 하나씩 작성된 함수를 통해 새로운 배열 형태로 반환한다.

각 요소에 id 값을 주기 위해 index를 추가로 작성할 수 있다.


'코딩 연습 > React' 카테고리의 다른 글

Component State with this.setState()  (0) 2019.01.10
PropTypes로 데이터 형태 확인하기  (0) 2019.01.07
블로그 이미지

쵸잇

,