Study/React

[React] 3. Component의 Props 와 State

momo02 2020. 10. 17. 16:24
반응형

1. Component의 props 와 state

  • 리액트 컴포넌트에서 다루는 데이터는 propsstate로 나뉜다.

  • props는 부모 컴포넌트에서 자식 컴포넌트로 전달하는 값이다 (-> 부모 컴포넌트에서 자식 컴포넌트로 전달하는 속성값들을 의미하는 'properties'의 줄임말) 자식 컴포넌트에서는 props를 받아오기만하고, 받아온 props를 직접 수정할 수 는 없다.

  • state는 컴포넌트 내부에서 선언하며 내부에서 관리되는 값이다. 값을 변경할 수 있다.

  • props 와 state 비교 및 정리 : props 와 state 는 둘다 일반 JavaScript 객체이다. 두 객체 모두 렌더링 결과물에 영향을 주는 데이터를 갖고 있으나 props는 함수의 매개변수처럼 컴포넌트에 전달 (전달받은 컴포넌트에서 수정 불가)되는 반면 state는 함수 내에 선언된 변수처럼 컴포넌트 안에서 관리된다.(선언된 컴포넌트 내부에서 수정 가능)
    즉, props는 일반적으로 고정적인 데이터를 전달할때 사용하고, state는 화면이 구성된 이후에도 계속 변경될 수 있는 데이터를 처리할 때 효율적으로 사용이 가능하다.


2. props 사용 예제

2-1. props를 사용하여 컴포넌트에 특정 데이터 전달하는 예제

[html]

<div id="root"></div>

[js]

function Show(props){
  return (
    <h3>
      Name is {props.name}
    </h3>
  );
}

//name 속성값으로 특정값("모모")을 전달
ReactDOM.render(<Show name="모모" />, document.getElementById('root'));

위 예제는 함수형 컴포넌트 방식으로 작성했다. (cf.클래스형 컴포넌트와의 주요 차이점은 state 와 lifeCycle 이 빠져있다는 점인데, 그래서 컴포넌트 초기 마운트가 아주 미세하게 빠르고, 메모리 자원을 덜 사용한다고 한다)
컴포넌트는 props를 입력으로 받아 리액트 요소를 반환하는 형태로 동작한다. Show 컴포넌트에 name 속성값으로 특정값("모모")을 전달 -> Show 컴포넌트는 전달받은 props의 name값을 이용해 요소를 반환했다.

  • Props 기본값 설정 : defaultProps

Show.defaultProps = {
  name : '홍길동'
}

ReactDOM.render(<Show />, document.getElementById('root'));

props 속성이 전달되지 않을 경우를 대비해, 위 코드와 같이 기본값을 설정할 수 있다.

 

[실행결과]

 

2-2. 부모 컴포넌트에서 자식 컴포넌트로 props(속성값들)를 전달하는 예제

[js]

function Show(props){
  return (
    <h3>
      Name is {props.name}
    </h3>
  );
}

function App() {
  return (
    <main>
      <Show name="모모"/>
      <Show name="춘도르"/>
      <Show name="빅룡"/>
    </main>
  )
}
ReactDOM.render(<App />, document.getElementById('root'));

App 컴포넌트에서는 자식으로 Show 컴포넌트를 3번 사용했다. 리액트 컴포넌트는 이렇게 컴포넌트 간 계층적으로 구성이 가능하며,
각 컴포넌트는 객체 지향적으로 구성되어 재사용성을 향상시킨다.

 

2-3. 컴포넌트의 props를 이용해 다양한 데이터를 속성 형태로 전달하는 게시판 예제

[js]

function User(props){
  return (
    <div>
      <img src={props.user.imageUrl}/>
      &nbsp;
      <strong>{props.user.name}</strong>
    </div>
  )
}

function Board(props){
  return (
    <section>
      <User user={props.user}/>
      {props.title}
      <hr/>
      {props.content}
    </section>
  );
}
// 사용자 정보는 User라는 함수형 컴포넌트가 그려줌 (계층적 구조)

const board = {
  title : '게시글 제목입니다.',
  content : '게시글 내용입니다. 반갑습니다.',
  user : {
    name : '모모',
    imageUrl : 'https://placeimg.com/32/32/any'
  }
}

ReactDOM.render(<Board title={board.title} content={board.content} user={board.user}/>, document.getElementById('root'))

[실행결과]

 


3. state 사용 예제

3-1-1. props를 이용한 초시계 예제

우선 props를 이용한 초시계 예제 코드를 먼저 작성해보고 이를 state 이용하여 변경할 것이다. 

[html]

<div id="root"></div>

[js]

class Clock extends React.Component {
  render() {
    return (
      <h3>현재 시각은 [{this.props.date.toLocaleTimeString()}] 입니다.</h3>
    );
  }
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()}/>,  document.getElementById('root')
  );
}
//1초에 한번씩 tick함수 수행 
setInterval(tick, 1000);

[실행결과]

위 예제는 외부에서 Clock 컴포넌트로 props를 이용해 데이터를 보내주는 방식이다. (props 의 'date'속성값에 현재시간을 전달)

굳이 컴포넌트 클래스의 외부에서 1초에 한번씩 어떠한 함수를 수행할 필요 없이 Clock이라는 클래스 내부에서 시간이 변경되도록 코드를 개선 해보자. 특정 컴포넌트 클래스의 내부적인 값이 변경되는 경우에는 props보다는 state를 사용하면 유용하다.

 

3-1-2. state를 이용한 초시계 예제

[js]

class Clock extends React.Component {
  //생성자를 명시, 명시하지 않은 경우에는 자동으로 props를 사용할수 있음.
  constructor(props) {
    super(props); //명시할 경우는 꼭 super를 이용해 전달받은 props를 초기화해줘야함
    this.state = {
      date : new Date()
    }
  }
  tick() {
    this.setState({
      //setState 함수를 이용해 현재 가지고 있는 date라는 state 값을 new Date()로 변경.
      date : new Date()
    })
  }
  //컴포넌트의 초기화(mount)가 끝났을 때 자동으로 호출되는 함수
  componentDidMount(){
    this.timerID = setInterval(() => this.tick(), 1000);
  }
  //리소스의 낭비를 없애기위해 컴포넌트가 Unmount될 때 clearIntervel 을 이용해 해당 intervel을 종료시킨다.
  componentWillUnmount(){
    clearIntervel(this.timerID);
  }
  render() { //클래스형 컴포넌트이기 때문에 반드시 render함수를 가진다.
             //클래스형 컴포넌트는 기본적으로 props를 내장하고 있어 this.props로 사용 가능.
    return (
        <h3>
        현재 시각은 [{this.state.date.toLocaleTimeString()}] 입니다.
        </h3>
    );
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'));

-  setState()는 컴포넌트의 state 객체에 대한 업데이트를 실행한다. state가 변경되면, 컴포넌트는 리렌더링된다. 

* 주의할 점은 state 값을 초기화 한 이후에는 반드시 setState함수를 사용하여 값을 변경해야한다는 것이다.

 

아래의 코드는 코드상의 오류는 발생되지않지만 state 값이 변경되지 않는다.

// state 값 변경 잘못된 예
this.state = {
   date : new Date()
}

이렇게 setState함수를 사용하여 state 값을 변경해야 한다.

// state 값 변경 올바른 예
this.setState({ 
  date : new Date()
})

[실행결과]

 

3-2. 버튼 이벤트를 이용해 state 값을 변경하는 예제

[js]

<div id="root"></div>

[html]

class Clock extends React.Component {
  //생성자를 명시, 명시하지 않은 경우에는 자동으로 props를 사용할수 있음. 
  constructor(props) {
    super(props); //명시할 경우는 꼭 super를 이용해 전달받은 props를 초기화해줘야함 
    this.state = {
      date : new Date()
    }
  }
  goBack() {
    let nextDate = this.state.date; //현재시간 객체를 가져옴
    //현재시간에서 10초 이전 시간으로 set.
    nextDate.setSeconds(nextDate.getSeconds() - 10);
    this.setState({
      date : nextDate
    })
 }
  render() { //클래스형 컴포넌트이기 때문에 반드시 render함수를 가진다. 
//클래스형 컴포넌트는 기본적으로 props 를 내장하고 있어 this.props로 사용 가능.
    return (
      <div>
        <h3>
         현재 시각은 [{this.state.date.toLocaleTimeString()}] 입니다.
        </h3>
        <button onClick = {this.goBack.bind(this)}>10초 뒤로가기</button>
       </div> 
    );
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'));

[실행결과]

더보기
  • 참조 강좌 및 블로그 출처

    YouTube 동빈나 [React JS 이론부터 실전까지] 강좌, https://ndb796.tistory.com/202 [안경잡이개발자] 

반응형