reactjs 에서 checkbox 가 동작하지 않는 경우 / reactjs 에서 체크박스 동작하기 / react props 와 state 연결
update, 2019-04-07
- React.Component – React
- React lifecycle methods diagram
- React.Component – React > UNSAFE_componentWillReceiveProps()
- You Probably Don't Need Derived State – React Blog
이제 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
은 아주 드물게 사용되어야 한다고 이야기 한다. 대체로 많이 하는 실수가
controlled
와 uncontrolled
를 혼용하는 것이다라고 이야기한다.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 를 변경해 주게 된다.이렇게 되면
controlled
와 uncontrolled
를 혼용하는 것이 된다.그래서 React 에서 Preferred Solutions 을 알려준다.
- fully controlled : 아예 state 가 없는 component 로 만들고, onChange 부분의 handler 로 props 로 빼는 방법
- 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 를 이용했다.
댓글 없음:
댓글 쓰기