[컴][웹] ReactJs 에서 checkbox 와 onChange


reactjs 에서 checkbox 가 동작하지 않는 경우 / reactjs 에서 체크박스 동작하기 / react props 와 state 연결


update, 2019-04-07

이제 ReactJS v15 에서 componentWillReceiveProps 는 더이상 사용하지 말라고 한다. 그리고 대신에 "getDerivedStateFromProps" 를 이용하라고 한다.


class Example extends Component {
  state = {
    filterText: "",
  };

  // *******************************************************
  // NOTE: this example is NOT the recommended approach.
  // See the examples below for our recommendations instead.
  // *******************************************************

  static getDerivedStateFromProps(props, state) {
    // Re-run the filter whenever the list array or filter text change.
    // Note we need to store prevPropsList and prevFilterText to detect changes.
    if (
      props.list !== state.prevPropsList ||
      state.prevFilterText !== state.filterText
    ) {
      return {
        prevPropsList: props.list,
        prevFilterText: state.filterText,
        filteredList: props.list.filter(item => item.text.includes(state.filterText))
      };
    }
    return null;
  }

  handleChange = event => {
    this.setState({ filterText: event.target.value });
  };

  render() {
    return (
      <Fragment>
        <input onChange={this.handleChange} value={this.state.filterText} />
        <ul>{this.state.filteredList.map(item => <li key={item.id}>{item.text}</li>)}</ul>
      </Fragment>
    );
  }
}

controlled/uncontrolled 의 혼용 방지

getDerivedStateFromProps 은 아주 드물게 사용되어야 한다고 이야기 한다. 대체로 많이 하는 실수가 controlleduncontrolled 를 혼용하는 것이다라고 이야기한다.

derived state 값을 다시 state 에 update 해야 하는 상황이라면(setState()) 이것은 async 같은 요청에서 많이 나오는데, server 로 request 를 보내서 response 를 받아서 그 값을 처리하는 경우를 보자.

이 때 response 로 받은 data 를 어떤 checkbox component(A 라고 하자) 에 prop 으로 넣어주게 되는데, 그러면 A 는 처음에 null 등의 props 값을 가지고 A 라는 component 를 set 한다.

하지만 A 는 checkbox 라서 component 내부에서도 state 가 계속 변경돼야 한다. 그래서 checkbox 의 값이 state 에 정의돼서 setState() 로 변경해야 한다.

이런 상황이라면 우리는 어쩔 수 없이 componentWillReceiveProps 를 사용하게 된다. 그래서 props 가 변하는 순간에 setState 를 호출해서 state 를 변경해 주게 된다.

이렇게 되면 controlleduncontrolled 를 혼용하는 것이 된다.

그래서 React 에서 Preferred Solutions 을 알려준다.
  1. fully controlled : 아예 state 가 없는 component 로 만들고, onChange 부분의 handler 로 props 로 빼는 방법
  2. full uncontrolled : props 값을 함수가 생성될때 state로 넘겨주고, 그 다음 완전히 state 로만 동작하도록 한다. 그리고 props 가 변경된 경우에는 key 값을 변경해서 component 가 완전히 새롭게 render 되게 하는 것.
<EmailInput
  defaultEmail={this.props.user.email}
  key={this.props.user.id}
/>



ReactJS 에서 checkbox 사용하기

check box 값을 dynamic 하게 설정 해 주기 위해 jsx syntax 에서 input 에 checked 를 설정해 주면, setState 를 불러야 하고, 그래서 기본동작(check box 를 눌면 check 가 되는) 이 동작하지 않았다. 그래서 아래와 같이 만들었다. 더 좋은 수가 있을 듯 한데...



CheckBox 를 state 와 함께 연동해서 사용하는 방법. 아래의 code 에서는
  • props 로 초기의 checked 값을 정해주고, 
  • check event 에 대한 처리

가 들어가 있다.


class MyCheckBox extends React.Component
 constructor: (props) ->
  super props
  @state = {
   checked: {}
  }

 render : ()->

  that = @
  clist = @props.cvalues.map (item, i)->
   
   `(
    <div className="checkbox" key={i}>
     <label>
      <input type="checkbox" value={item.value}
       checked={that.state.checked[item.value]}
       onChange={that.onCheckboxChangeHandler} />
      {item.text}
     </label>
    </div>

   )`

  `(
   <div className="mfCheckBox form-group" ref="chkbox">
    {clist}
   </div>

  )`

 componentWillReceiveProps: (nextProps)->
  # 여기서 props 를 state 에 넣어준다.
  @setState
   checked : nextProps.checks
  return

 onCheckboxChangeHandler: (e)=>
  @setState (state)->
   state.checked[e.target.value] = e.target.checked
   return {
    checked : state.checked
   }
  return



select, input 등 다른 form

참고로, 이방법은 다른 form 에도 같은 문제 때문에 이런 방법이 필요하다. select 나 input 등의 다른 form 에도 적용하면 된다.

혹시나, 자신이 만든 select 등의 component 가 선택을 해도 바뀌지 않는 등의 문제가 있다면 한 번 확인해 보자.

참고

input type=text 같은 경우에 value , onChange 를 지정하지 않으면, 일반적인 element 처럼 동작한다. 하지만 value="" 이런 식으로 input 의 attribute value 를 지정해 놓으면 typing 을 해도 값이 update 가 되지 않는다.



삽질후기

처음에 그냥 props 를 이용해서 checked 를 할당했다. 그런데 그렇게 되면 checkbox onChange event 에 대해서 처리할 때 onCheckboxChangeHandler 에서 setProp 을 해주면 될 듯 했다. 하지만, 이녀석은 이제 deprecated 되었다. 결국 setState 로 처리를 해줘야 했다.

그래서 이 부분을 위해서 checked={} 부분을 state 를 사용하도록 수정했다.

props 를 통해 "처음 checked={} 값을 할당"하기 위해 componentWillReceiveProps 를 이용했다.




Reference

  1. Forms | React
  2. javascript - React js cant change checkbox state - Stack Overflow

댓글 없음:

댓글 쓰기