게시글

5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭
강좌3 - React - 8년 전 등록 / 4년 전 수정

Props, State

안녕하세요. 이번 시간에는 동적 컴포넌트를 위한 필수요소 PropsState에 대해 알아보겠습니다! 일단 지난 시간에 사용한 Basic 컴포넌트를 재사용하겠습니다! 조금 많이 수정했으니 찬찬히 살펴보세요.

import React, { Component } from 'react';
import PropTypes from 'prop-types'; // 패키지 추가

class Basic extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hidden: false,
    };
  }

  render() {
    return (
      <div>
        <span>저는 {this.props.lang} 전문 {this.props.name}입니다!</span>
        {!this.state.hidden && <span>{this.props.birth}년에 태어났습니다.</span>}
        <button onClick={() => this.setState(() => ({ hidden: true }))}>숨기기</button>
      </div>
    );
  }
}
Basic.propTypes = {
  name: PropTypes.string.isRequired,
  birth: PropTypes.number.isRequired,
  lang: PropTypes.string,
};
Basic.defaultProps = {
  lang: 'Javascript',
};

export default Basic;

이번 시간에 배울 propsstate를 추가해보았습니다. 일단 소개부터 하겠습니다!

Props

props는 부모 컴포넌트로부터 물려받는 속성입니다. 이를 통해 부모 컴포넌트와 소통할 수도 있죠. 부모 컴포넌트에서 전달하는 props가 바뀌면 자동으로 업데이트됩니다. render.js에서 다음과 같이 바꿉니다.

render(<Basic name="Zero" birth={1994} />, document.getElementById('root'));

이전 시간과는 달리, 부모 컴포넌트에 Basic 컴포넌트를 부착하는 부분에서 추가적인 속성을 주었습니다. name 속성의 값은 "Zero"로, birth 속성의 값은 1994로 주었네요. 바로 이게 props입니다. 컴포넌트 내에서 this.props.속성이름으로 접근가능합니다. 위의 Basic 컴포넌트를 다시 보면, this.props.namethis.props.birth가 있죠? 이 부분이 각각 Zero와 1994로 치환됩니다.

Zero는 따옴표로 감쌌는데 birth는 { }로 감쌌습니다. props는 html처럼 기본이 문자열이기 때문에 다른 자료형을 전달하려면 { } 안에 넣어야 합니다.

defaultProps

다시 Basic 컴포넌트를 보면, this.props.lang이 있는데 부모 컴포넌트에서는 lang을 주지 않았습니다. 그런데도 Javascript로 치환되었습니다.

<span>저는 {this.props.lang} 전문 {this.props.name}입니다!</span>

어떻게 이런 일이 일어날 수 있을까요? 바로 defaultProps이기 때문입니다. class 아랫부분을 보면 Basic.defaultProps = { ... } 로 lang을 Javascript로 만들었습니다. 만약 부모 컴포넌트에서 따로 lang 속성을 넘겨주지 않는다면 자동으로 defaultProps가 적용됩니다.

propTypes

npm install prop-types

prop-types 패키지를 설치합니다.

Basic.propTypes = {
  name: PropTypes.string.isRequired,
  birth: PropTypes.number.isRequired,
  lang: PropTypes.string,
};

그 위에 설명하지 않은 propTypes에 대해서 알려드리겠습니다. propTypes에 보면 name, birth, lang에 대한 내용이 들어있습니다. PropTypes 객체는 prop-types 패키지를 따로 설치해야 쓸 수 있습니다. 그리고 string, number, isRequired 등등이 나와 있네요. 바로 React의 props 자료형 검사법입니다.

propTypes에 정의해두었으면 React가 해당 props가 propTypes의 자료형과 일치하는지 검사합니다. 다를 경우 에러를 내보내고요. name이 string으로 되어있는데, number이 들어왔을 경우 에러가 나는 거죠. isRequired는 필수라는 뜻입니다. name과 birth 속성은 반드시 있어야 한다는 것이죠. 자료형도 일치해야 하고, 필수적으로 넣어주어야 합니다. isRequired가 붙지 않으면 선택적이라는 뜻입니다. 다양한 종류의 propTypes가 있는데 여기에서 확인하세요.

children

추가적으로 props에는 children 이라는 것이 있습니다.

const Parent = () => {
  return (
    <div id="parent">{this.props.children}</div>
  );
};

위와 같은 컴포넌트가 있다면 보통 <Parent /> 이렇게만 사용하는데요.

<Parent>
  <span>Hello</span>
</Parent>

위와 같이 내용물을 넣어줄 수 있습니다. 안에 넣은 span 태그는 this.props.children과 연결됩니다. 따라서 결과적으로는 다음과 같이 됩니다.

<div id="parent"><span>Hello</span></div>

State

만약 hooks에 추가된 useState를 배워보려고 하시는 거라면 이 링크 를 클릭해주세요! hooks를 배우더라도 class 컴포넌트의 state 사용법도 알아두시는 게 좋습니다.

constructor() {
  this.state = {
    hidden: false,
  };
} 

constructor 안을 보면 state라는 것이 보입니다. state는 컴포넌트가 만들어질 때 가장 먼저 설정되는 것이기 때문에 constructor 안에 적어줍니다.

state는 해당 컴포넌트에만 적용되는 상태입니다. 예를 들면, 내비게이션 메뉴를 켜고 끌 때 state에 on/off 상태를 등록해둘 수 있습니다. 역시 props처럼 자동으로 업데이트되어 편합니다.

위의 예를 보시면 처음에 state에 hidden이 기본으로 설정된 것을 보실 수 있습니다. 그리고

{!this.state.hidden && <span>{this.props.birth}년에 태어났습니다.</span>}

에서 this.state.hidden === false인 경우 다음 span 태그를 추가하라고 코딩되어있습니다. 삼항 연산자처럼 React에서는 &&이나 ||를 사용하여 render 여부를 결정할 수 있습니다. if를 jsx 내에서 사용할 수 없기 때문에 다른 방법을 사용하는 겁니다.

<button onClick={() => this.setState(() => ({ hidden: true }))}>숨기기</button>

위 버튼은 눌렀을 때 hidden state를 true로 만들라고 되어있네요. 일반 html과 달리 onclick이 아니라 onClick임을 주의해주세요. 대소문자를 확실하게 구분하셔야 합니다.

보통 어떤 것을 state로 만들까요? 저는 화면이 바뀌는 것에 관한 데이터을 state로 만들어둡니다. hidden state에 따라 span 태그가 보여질지 말지가 결정됩니다. state를 바꾸면 알아서 화면이 다시 그려지는 것이죠. 따라서 화면을 다시 그려야하는 상황에서, 다시 그려야할지 판단하는 데이터가 state가 됩니다. 핵심은 react에서는 화면을 변경(dom 조작)하는 것이 아니라 데이터를 변경해야 된다는 것입니다. 화면은 데이터에 따라서 알아서 바뀌는 것이고요.

state들은 다른 컴포넌트에 props를 통해 넘겨줄 수 있습니다.

setState

잠깐 state 설정법에 대해서 알아보자면, state를 바꾸려면 this.state.이름 = 바꿀 값; 이렇게 하는 것이 아니라, this.setState((이전 상태) => ({ 이름: 바꿀 값 })); 이렇게 하는 겁니다. setState 메소드를 사용해야 함을 꼭 기억하세요.

setState의 콜백 함수는 매개변수로 이전 상태를 제공합니다. 예를 들어 어떤 버튼을 눌렀을 때 hidden을 true에서 false로, false에서 true로 토글하고 싶다면 this.setState(prevState => ({ hidden: !prevState.hidden })) 하면 됩니다. 알아서 이전 상태와 반대로 값을 바꿔줍니다.

다시 본론으로 돌아가서 저 버튼을 누르면 바로 1994년에 태어났습니다. 라는 문장이 사라집니다! 자동으로 반응하기 때문에 state를 조작만 하면 됩니다.

지금까지 배운 props와 state로 동적 컴포넌트를 만들어보세요. 다음 시간에는 React 이벤트 바인딩에 대해서 살펴보겠습니다!

조회수:
0
목록
투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.
5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭

댓글

5개의 댓글이 있습니다.
4년 전
인프런 강좌 보다가 가끔 이해 안되는 부분 블로그 포스팅 글을 보면서 다시 한번 복습하는데 이렇게 상세히 잘 설명해주시니 덕분에 이해가 쉽게 가는군요 ㅎㅎ 감사합니다!!
6년 전
만약 Create-react-app으로 리액트 앱을 만들었다면 constructor(props)로 파라미터를 넣고, 그 다음줄에 super(props)을 적어야 에러가 뜨지 않습니다. 그리고, 1번째 줄도 import React, { Component } from 'react'; 로 적어주셔야 합니다(PropTypes 제거) 이유는 잘 모르겠네요
6년 전
감사합니다. 수정했습니다.
6년 전
this.props.lang 에서 this는 Basic 컴포넌트(부모 컴포넌트)를 가리키는 게 맞나요?
6년 전
네 맞습니다~ 근데 리액트의 this는 살짝 복잡하게 구성되어 있습니다. console.log찍어보세요~
6년 전
고맙습니다!
7년 전
생성자에서 hidden값을 false로 초기화 하고 있는데 15줄 설명을 보면 앞에 !가 붙어있는데 이건 hidden이 true일때 태어난 birth를 보여준다는 의미 아닌가요??
7년 전
hidden이 false여야 !this.state.hidden이 true가 되어 birth를 보여주는 겁니다.
7년 전
네 저도 그리 생각했는데 본문에는
' this.state.hidden === false인 경우 다음 span 태그를 추가하라고 코딩되어있습니다. ' 라고 되어있어서 본문이 잘못됐거나 위에 초기화 하신게 잘못된게 아닐까하고 여쭤봤습니다.
7년 전
아뇨 맞습니다. this.state.hidden === false랑 !this.state.hidden === true는 같은 뜻입니다.
7년 전
{!this.state.hidden && \u003cspan>{this.props.birth}년에 태어났습니다.\u003c/span>}
이 코드에서 hidden 값은 true가 아닌가요?
7년 전
아 이해했습니다. 감사합니다.
7년 전
setState 포스팅이 오래돼서 방금 전 살짝 수정했습니다. this.setState를 할 때 안에 함수를 넣어주는 게 표준입니다. this.setState({ 새: 상태 }) 대신 this.setState(() => ({ 새: 상태 })) 이렇게 해야 합니다.
8년 전
setState는 선언되어 있지 않아도 사용가능한건가요??
8년 전
질문이 살짝 모호하네요. setState자체는 this(컴포넌트)의 메소드라 기본 제공됩니다.
8년 전
아 기본제공이구나 ..ㅎㅎ 글다읽어보고나서 알았네여 ㅋㅋㅋ 재밌게 잘보고있습니다.