[컴][웹] React 의 간단한 이해

react 의 property / state / state 의 뜻 / reactjs



React 는 View(html tag 의 조합) 를 만들기 위한 것이다. (물론 디테일은 다르다. 이것과 관련된 이야기는 여기서 하자.)그런데 이 view 를 좀 더 동적으로 변경시킬 수 있게 하기 위해 이 component 가 변수를 갖게 됐다. 여기서는 이 변수의 의미를 살펴보면서 이 변수를 이용해서 어떻게 React 를 사용하는지 살펴보자.


prop, state 의 차이

prop 은 한 번 지정하면, 바꾸지 않을 값이고,
state 는 계속해서 바꾸는 값이다.
의미를 생각하면 쉽다. property(속성) 은 그 객체가 가진 고유한 속성이니까 바뀌지 않는 값이며, state(상태) 는 그 객체의 현재 기분같은 것이라서 바뀔 수 있는 값이다.

댓글의 '최민규' 님이 아래 처럼 이야기 해주셨다. 개인적으로도 훨씬 이해가 잘 되는 설명같다.
  • props는 상위 컴포넌트에서 전달하는 것 --> 하위 컴포넌트에서 수정을 못한다.
  • state는 해당 컴포넌트가 자기 자신의 상태를 제어하기 위한 값 -->  수정할 수 있는 것
그런데 prop 으로 지정한 값이 state 에 initial value 로 동작하길 원하는 경우도 있다. 예를 들면 checkbox 의 값이 처음에는 parent component 의 상태로 값이 결정되지만, 추후에는 checkbox 에 대한 click event 로 결정된다. 이 경우에 componentWillReceiveProps  함수를 이용해서 처음prop 으로 넘어온 값을 state 에 다시 할당해 주는 과정을 거치면 된다.(참고)



prop

<Shop owner="Me">Grocery</Shop>

위의 code 에서 Shop 의 props 은 아래와 같이 생성된다.
props = {
  owner : "Me",
  children : "Grocery"
}

간단하게 생각하면, prop 은 parameter 같은 녀석이다. html element 에서는 이것을 속성(attribute) 라고 부르지만, 함수로 생각하면 parameter 이다. 이 녀석이 React 에서는 property 가 되는 것이다. 부르는 호칭만 다르지, 의미는 대동소이하다.

state

React 에서 이야기하는 state 는 필자의 의견으로는 check box 를 연상하는 것이 좋은 방법이 될 듯 하다. 우리가 check box 를 click 하면 어떤 상태(state) 인지를 표시하는 것이 되고, 이것을 기반으로 화면이 변화가 생긴다. 이렇게 값이 변하는 속성(property) 이 state 라고 보면 된다.

좀 더 정확한 설명은 ref. 1을 확인하자.


prop 관련 함수

getDefaultProps

getInitialState 와 같은 역할을 한다.



State 관련 함수

state 와 관련해서 몇가지 함수를 살펴보자.

getInitialState

내가 만든 component 에 초기 state 값을 주고 싶다면 getInitialState 를 정의하면 된다. react.js 는 처음에 initialState 를 set 하기 위해 getInitialState() 를 호출하기 때문이다. 사용법은 아래 코드를 참고하자.

setState

이렇게 생성된 state 값을 변경할 때는 setState({}) 를 사용하면 된다.




DOM 관련 API

componentDidMount


이녀석은 여기서 component (html tag의 조합이라 보면 된다.) 를 dynamic 하게 만들기 때문에, 이녀석의 DOM 이 만들어진 이후에 작업을 해야 할 일이 있을 수 있다. 그 때 사용하면 된다. mount 됐다는 이야기가 document 에 attach 된 상태는 아니라고 한다. 그냥, initialized and rendered 라고 한다.

var CommentBox = React.createClass({
  getInitialState: function() {
    return {
      data: []
    };
  },

  componentDidMount: function() {
    this.setState({
      data: "testtestest"
    });
    this.loadCommentsFromServer();
    return setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },

  render: function() {
    return (
   <div className="commentBox">
    Hello, world!
    <h1>Comments</h1>
    <CommentList data={this.state.data}/>
    <CommentForm onCommentSubmit={this.handleCommentSubmit}/>
   </div>
  );
  }
});

이부분은 사실 lifecycle 관련 method 와 연관이 되어 있다. 여기를 참고하자.


  1. Mounting: componentWillMount
  2. Mounting: componentDidMount : 한번만 호출된다. 처음 render 후, mount 될때
  3. Updating: componentWillReceiveProps : 그리고, props 가 변할 때 setState() 를 호출해서 state 를 변경해야 하는 경우라면 여기를 이용하자.
    이 함수에서 setState() 를 호출해도 render 를 다시 호출하지 않는다. 그러므로 setState() 를 사용하려면 여기서 해야 한다.
  4. Updating: shouldComponentUpdate : update (render() 호출)를 하는지 여부를 결정할 수 있다. 관련해서는 ref. 3 를 읽어보자.
  5. Updating: componentWillUpdate
  6. Updating: componentDidUpdate
  7. Unmounting: componentWillUnmount



ref 속성 : refs

React 가 component 를 만드는 것을 해주고, 이것을 동적으로 다룰 수 있게 해준다. 그런데, 내가 만든 component 가 여러개의 element 로 이뤄졌을 경우, 이 녀석들을 구분해서 접근할 수 있어야 한다. 이런 역할을 해주는 것이 ref attribute 이다.

ref 속성을 이용해서 element 를 우리가 만든 component 에서 바로 접근할 수 있도록 해준다. 아래 예제를 참고하자.


ReactDOM.findDOMNode

ref="author" 라고 하면, this.refs.author 로 input instance 를 접근할 수 있게 해준다. 실질적인 HTML DOM 은 React.findDOMNode 함수를 통해 접근해야 한다.



CommentForm = React.createClass(
 handleSubmit : (e)->
  e.preventDefault()

  author = ReactDOM.findDOMNode(this.refs.author).value.trim()
  text = ReactDOM.findDOMNode(this.refs.text).value.trim()
  if not text or not author
   return
  

  # TODO: send request to the server
  ReactDOM.findDOMNode(this.refs.author).value = ''
  ReactDOM.findDOMNode(this.refs.text).value = ''
  return


 render : ()->
  `(
   <form className="commentForm" onSubmit={this.handleSubmit}>
    <input type="text" placeholder="Your name" ref="author" />
    <input type="text" placeholder="Say something..." ref="text" />
    <input type="submit" value="Post" />
   </form>
  )`
)



propTypes

이 녀석은 type 검사 같은 것을 해준다. 뭐 필요없을 수도 있지만, 개인적으로 필요하다고 생각하는 녀석이다.

var MyComponent = React.createClass({
  propTypes: {
    children: React.PropTypes.element.isRequired
  },

  render: function() {
    return (
      <div>
        {this.props.children} // This must be exactly one element or it will warn.
      </div>
    );
  }

});



child Component

만약 아래처럼 child component 를 갖는 경우에 parent 에 이녀석을 처리하려면 this.props.children 을 이용하면 된다. 참고로 child 가 한개면 그냥 component 를 주고, 여러개 이면, array 를 넘겨준다.
<MyParent>
     <MyChild1/>
     <MyChild2/>
</MyParent>



React.PureComponent


ref. 3 을 보면 나오는데, PureComponent 는 state 나 prop 이 변경된 때에만 render() 를 호출하고 싶은 component 를 만들 때 쓰면 된다.

이녀석은 React.Component 와 같다. 그런데, 단지 render() 를 호출하기전에 state 나 prop 의 변경이 있는지 여부를 보고, 변경된 사항이 있으면 render() 를 호출한다. 그런데 이 비교를 대충하는 것이니(shallow comparison), 실제로 detail 한 비교를 하려면 shouldComponentUpdate  를 직접 작성해야 한다고 한다. 자세한 사항은 ref. 3을 참고하자.


See Also

  1. Thinking in React | React
  2. Top-Level API | React
  3. https://github.com/i5on9i/reactjstemplate

Reference

  1. Interactivity and Dynamic UIs | React
  2. Tutorial | React
  3. Optimizing Performance - React







댓글 2개:

  1. props는 상위 컴포넌트에서 전달하는 것이기 때문에 하위 컴포넌트에서 수정을 못하는 것이고 state는 해당 컴포넌트가 자기 자신의 상태를 제어하기 위해 수정할 수 있는 것이라는 표현이 더 정확한거 같네요. propTypes는 해당 컴포넌트가 받을 수 있는 props에 대한 유효성 검사도 실행할 수 있을 뿐만 아니라 어떤 props가 전달되는지도 확인가능하므로 props가 전달되는 컴포넌트는 다 작성해주시는게 좋습니다.

    답글삭제
    답글
    1. 네, 좋은 답변 감사합니다. 본문에도 적어넣었습니다.

      삭제