'전체 글'에 해당되는 글 88건

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
블로그 이미지

쵸잇

,

Moment 앱 따라하기

배경화면으로 쓰일 이미지를 랜덤으로 출력 위해 Math 내장객체에서 floor(), random() 메소드를 활용한다.


html 파일에서 body 요소를 가져온다.


  • 웹브라우저 화면 전체를 이미지로 씌울 예정이므로 body를 통째로 가져온다.


const body = document.querySelector("body");




1부터 시작하는 정수를 랜덤하게 뽑는 함수를 만든다.


  • Math.random()은 1이하의 실수를 랜덤으로 반환한다.
  • Math.floor()는 실수를 소수점 내림하여 정수 형태로 반환한다.
  • 0부터 숫자가 반환되므로 더하기 1을 하여 숫자 1부터 변수로 지정되도록 한다.


// 가지고 있는 배경사진 갯수
const IMG_NUMBER = 3;
function
genRandom(){

    // Math.random()은 1 이하의 실수를 랜덤으로 출력한다 (0.XXXXXX 형태로)
    // 3을 곱한다해도 숫자 3을 넘지 못하는 실수 형태의 숫자를 출력한다

    // Math.floor()는 소수점 내림을 하여 실수 형태를 정수로 만든다
    // 따라서 Math.floor(Math.random())는 "0"만 출력한다
    // Math.floor(Math.random() * 3)은 "0, 1, 2"까지 출력 가능하다
    // Math.ceil()은 소수점 올림을 한다
   
    // IMG_NUMBER는 3 이므로
    const number = Math.floor(Math.random() * IMG_NUMBER) + 1;
   
    // 0, 1, 2 중에 하나를 반환한다
    return number;
}



  • 배경사진의 개수가 3개라서 IMG_NUMBER 변수에 3을 담았다.
  • 이미지 개수에 맞게 임의로 하나의 숫자를 뽑아서 해당 숫자의 파일명을 가진 이미지를 가져올 것이다.



랜덤으로 뽑힌 숫자랑 같은 이름의 이미지 파일을 호출한다.


  • 랜덤으로 뽑은 숫자를 함수의 인자로 사용한다.
  • new Image() 메소드를 사용하여 html<img>를 만드는데, 이는 우리가 출력할 <img src="">가 담긴다.
  • <img src="">images 폴더에 있는 이미지 파일을 지정한다.
  • 그 이미지 파일은 랜덤으로 가져와야 하므로 imgNumber 파라미터를 통해 랜덤 숫자를 받는다


function paintImage(imgNumber) {

    // <img> 태그를 만들어준다
    const image = new Image();
    // document.createElement('img')와 같은 코드를 나타낸다
  
    // <img src=""> 이미지 파일의 소스를 입력한다
    // 랜덤 숫자에 +1을 하는 이유는 이미지 파일이 1부터 시작하므로
    image.src = `images/${imgNumber}.jpg`;
  
    // <img src="" class=""> 이미지 효과를 위해 클래스를 추가한다
    image.classList.add("bgImage");
   
    // <body>에 완성된 <image>를 자식요소로 삽입하기
    body.appendChild(image);
}


  • 배경사진이 원본 그대로 노출되면 웹브라우저에 맞지 않으므로, CSS를 통해 약간의 수정을 한다.
  • 완성된 image 변수를 body에 자식요소로 추가한다



배경사진의 크기를 조절하고 동시에 애니메이션 효과를 준다. 


  • animation 속성을 사용하기 앞서 @keyframes를 작성한다.
  • 투명도(opacity)를 0에서 1로 변화를 주어 자연스럽게 화면이 전환될 수 있게 한다.
  • top, left 크기를 0로 하여 텍스트로 인해 비어있는 상단, 왼쪽 공간을 제거한다. 
  • 웹브라우저 화면 크기에 맞도록 widthheight 비율을 100%로 작성한다. 
  • 텍스트가 배경사진 앞에서 노출될 수 있도록 z-index 속성을 이용해 레이어 순서를 조절한다.


/* 애니메이션으로 쓸 효과(fadeIn)를 설정한다 */
/* 사진의 투명도를 조절하여 안보이다가 보이게 한다 */
@keyframes fadeIn {
    from {
        /* 투명도 설정 */
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

.bgImage {
    /* 절대적인 위치를 계산한다 */
    position: absolute;
    top: 0;
    left: 0;
    /* 웹브라우저에 맞게 사이즈를 조절한다 */
    width: 100%;
    height: 100%;

    /* 쌓여있는 레이어 순서. -1을 입력하면 사진이 뒤로 밀리고 텍스트가 앞으로 온다 */
    z-index: -1;

    /* 0.5초 서서히 사진이 나타난다 */
    animation: fadeIn 0.5s linear;
}



genRandom() 함수와 printImage() 함수를 순차적으로 실행시킨다.


  • genRandom() 함수를 통해 랜덤으로 뽑은 숫자를 printImage() 함수의 인자로 사용한다


function init(){
    // 랜덤으로 받은 숫자를 변수 지정
    const randomNumber = genRandom();

    // 받은 숫자를 이미지를 선택하는 함수에 전달한다
    paintImage(randomNumber);
}

init();


블로그 이미지

쵸잇

,