본문 바로가기

프로그래밍/ReactJS

[React] Chapter3. 컴포넌트

Chapter3. 컴포넌트

리액트를 다루는 기술, 서적을 공부하면서 요약 정리한 내용이다.

3.1 첫 컴포넌트 생성

  • scr/MyComponent.js
      import React, { Component } from 'react';

      class MyComponent extends Component {
          render() {
              return (
                  <div>
                      나의 새롭고 멋진 컴포넌트
                  </div>
              );
          }
      }

      export default MyComponent;
  • Reactjs Code Snippet 활용

3.1.1 모듈 내보내기

  • export
export default MyComponent;

3.1.2 모듈 가져오기

  • import
      import React, { Component } from 'react';
      import MyComponent from './MyComponent';  // MyComponent 파일을 불러오기

      class App extends Component {
        render() {
          return (
            <MyComponent/>
          );
        }
      }

      export default App;

3.2 props

  • props 란?
    • properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소
    • props 값은 부모 컴포넌트에서만 사용 가능.
      • 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서만 설정 가능.

3.2.1 props 랜더링 & props 값 설정

  • props에 name을 랜더링
      import React, { Component } from 'react';

      class MyComponent extends Component {
          render() {
              return (
                  <div>
                      hello i'm properties {this.props.name}.
                  </div>
              );
          }
      }
      export default MyComponent;
  • props에 값 세팅, 부모에서 가능!
      import React, { Component } from 'react';
      import MyComponent from './MyComponent';

      class App extends Component {
        render() {
          return (
            <MyComponent name="React"/>
          );
        }
      }

      export default App;

3.2.2 props 기본 값 설정: defaultProps

  • 전통적인 방식
      import React, { Component } from 'react';

      class MyComponent extends Component {
          render() {
              return (
                  <div>
                      hello i'm properties {this.props.name}.
                  </div>
              );
          }
      }

      MyComponent.defaultProps = {
          name: 'default name'
      }

      export default MyComponent;
  • ES6 transform-class-properties 문법 (일반적인 ES6 문법이 아니다.)
      import React, { Component } from 'react';

      class MyComponent extends Component {
          static defaultProps = {
              name: 'default name'
          }
          render() {
              return (
                  <div>
                      hello i'm properties {this.props.name}.
                  </div>
              );
          }
      }

      export default MyComponent;

3.2.3 props 검증: propTypes

  • propTypes
    • 컴포넌트의 필수 props를 지정 혹은 props 타입을 지정할 때 사용
    • PropTypes 임포트해야 사용 가능
  • class 외부
      import React, { Component } from 'react';
      import PropTypes from 'prop-types';

      class MyComponent extends Component {
          static defaultProps = {
              name: 'default name'
          }
          render() {
              return (
                  <div>
                      hello i'm properties {this.props.name}.
                  </div>
              );
          }
      }

      MyComponent.propsTypes = {
          name: PropTypes.string  // name props 타입을 문자열로 설정.
      }

      export default MyComponent;
  • class 내부
      import React, { Component } from 'react';
      import PropTypes from 'prop-types';

      class MyComponent extends Component {
          static defaultProps = {
              name: 'default name'
          }
          static propTypes = {
              name: PropTypes.string
          }
          render() {
              return (
                  <div>
                      hello i'm properties {this.props.name}.
                  </div>
              );
          }
      }

      export default MyComponent;
  • 문자열에 숫자를 넣을 경우
      import React, { Component } from 'react';
      import MyComponent from './MyComponent';

      class App extends Component {
        render() {
          return (
            <MyComponent name={3} />   // 문자열 외의 타입은 {}으로 감싸줘야 한다. 안그럼 컴파일에러 발생.
          );
        }
      }

      export default App;

propTypes를 문자열로 설정하고 숫자를 넣었을 경우 에러발생

  • 필수 propTypes 설정
    • isRequired
          import React, { Component } from 'react';
          import PropTypes from 'prop-types';

          class MyComponent extends Component {
              static defaultProps = {
                  name: 'default name',
              }
              static propTypes = {
                  name: PropTypes.string,
                  age: PropTypes.number.isRequired    // 필수적으로 존재해야하며, 숫자입니다.
              }
              render() {
                  return (
                      <div>
                          <p>Hello, my name is {this.props.name}.</p>
                          <p>I'm {this.props.age}.</p>
                      </div>
                  );
              }
          }

          export default MyComponent;

  • defaultProps와 propTypes의 활용 여부
    • 필수는 아니나, 협업시 타입을 바로 알 수 있어서 도움이 된다.
    • 즉, 사용을 권장함.

3.3 state

  • state
    • 컴포넌트 내부에서 읽기 & 업데이트 → state를 사용해야함.
      • props는 읽기 전용.
    • "state 초기값 설정 → state 랜더링 → state 값 업데이트" 로 진행된다.
    • this.setState(), 메서드로만 값을 업데이트 해야함.

3.3.1 컴포넌트의 생성자 메서드: constructor()

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class MyComponent extends Component {
    static defaultProps = {
        name: 'default name',
    }
    static propTypes = {
        name: PropTypes.string,
        age: PropTypes.number.isRequired    // 필수적으로 존재해야하며, 숫자입니다.
    }

        // 생성자 내부에서 state의 초기값을 설정!
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>
                <p>Hello, my name is {this.props.name}.</p>
                <p>I'm {this.props.age}.</p>
            </div>
        );
    }
}

export default MyComponent;
  • 코딩
    • MyComponent는 Component 클래스를 상속.
    • 부모 클래스의 constructor()를 호출.
    • super()

3.3.2 state 초깃값 설정 & 3.3.3 랜더링

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class MyComponent extends Component {
    static defaultProps = {
        name: 'default name',
    }
    static propTypes = {
        name: PropTypes.string,
        age: PropTypes.number.isRequired    // 필수적으로 존재해야하며, 숫자입니다.
    }
    constructor(props) {   //props 넣지않아도 작동한다. 에러도 없다. 직관적으로 이해하기위한 약속으로 생각하면 되지 않을까 싶다.
        super(props);
        this.state = {  // 초기값 설정.
            number: 0
        }
    }
    render() {
        return (
            <div>
                <p>Hello, my name is {this.props.name}.</p>
                <p>I'm {this.props.age}.</p>
                <p>Number: {this.state.number}.</p>
            </div>
        );
    }
}

export default MyComponent;

3.3.4 setState()

this.setState(), 로 값을 업데이트 한다.

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class MyComponent extends Component {
    static defaultProps = {
        name: 'default name',
    }
    static propTypes = {
        name: PropTypes.string,
        age: PropTypes.number.isRequired    // 필수적으로 존재해야하며, 숫자입니다.
    }
    constructor(props) {   //props 넣지않아도 작동한다. 에러도 없다. 직관적으로 이해하기위한 약속인가?
        super(props);
        this.state = {  // 초기값 설정.
            number: 0
        }
    }
    render() {
        return (
            <div>
                <p>Hello, my name is {this.props.name}.</p>
                <p>I'm {this.props.age}.</p>
                <p>Number: {this.state.number}.</p>  { /** 랜더링 */ }
                <button onClick={() => {
                        this.setState({
                            number: this.state.number + 1
                        });
                    }
                }>PLUS</button>
            </div>
        );
    }
}

export default MyComponent;

3.3.5 state를 constructor에서 꺼내기

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class MyComponent extends Component {
    static defaultProps = {
        name: 'default name',
    }
    static propTypes = {
        name: PropTypes.string,
        age: PropTypes.number.isRequired    // 필수적으로 존재해야하며, 숫자입니다.
    }
    // constructor(props) {   //props 넣지않아도 작동한다. 에러도 없다. 직관적으로 이해하기위한 약속인가?
    //     super(props);
    //     this.state = {  // 초기값 설정.
    //         number: 0
    //     }
    // }
    state = {
        number: 0
    }
    render() {
        return (
            <div>
                <p>Hello, my name is {this.props.name}.</p>
                <p>I'm {this.props.age}.</p>
                <p>Number: {this.state.number}.</p>  { /** 랜더링 */ }
                <button onClick={() => {
                        this.setState({
                            number: this.state.number + 1
                        });
                    }
                }>PLUS</button>
            </div>
        );
    }
}

export default MyComponent;
  • transform-class-properties 문법으로 constructor 바깥에서 정의 가능하다.

3.3.6 state 값을 업데이트할 때 주의 사항

// 잘못된 코드
this.state.number = this.state.number + 1;
this.state.someArray.push(3);
this.state.someObject.value = 3;
  • 반드시 setState() 메서드를 통해서 업데이트 해야한다.
    • setState() 메서드가 하는 역할은 파라미터로 전달받은 필드를 업데이트한 후 컴포넌트가 리랜더링하도록 트리거하는 것.
    • 때문에, 직접 state에 접근해서 값을 수정하면 컴포넌트를 자동으로 리랜더링하지 않는다.
    • 배열이나 객체는 사본을 만들어서 값을 세팅한다음 사본을 업데이트하는 방식을 사용한다.
      • 8장에서 다룰예정.

3.4 정리

  • props, state의 사용법
    • props는 부모컴포넌트가 설정한다.
    • state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트한다.
  • props 활용
    • 부모 컴포넌트 state → 자식 컴포넌트의 props로 설정
    • 부모의 상태가 바뀌면 자식의 props도 유동적으로 변화하도록 응용이 가능하다.
  • 참고문헌
    리액트를 다루는 기술