-
리액트 주요개념 - 폼IT/리액트 2022. 1. 16. 01:32728x90
제어 컴포넌트 (Controlled Component)
JavaScript 함수로 폼의 제출을 처리하고 사용자가 폼에 입력한 데이터에 접근 할 수 있도록 도와주는 기술
HTML에서 폼 엘리먼트(input, select, textarea, ..)는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트합니다.
그러나 React에서는 변경할 수 있는 state가 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트됩니다. 이때 React state를 신뢰가능한 단일 출처(single source of truth)로 만들어 두 요소를 결합할 수 있습니다. 그러면 폼을 렌더링하는 React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어할 수 있고 이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 제어 컴포넌트라고 합니다.
제어 컴포넌트 예시:
class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } function Form() { return ( <div> <NameForm /> </div> ) }
value 어트리뷰트는 폼 엘리먼트에 설정되므로 표시되는 값이 항상 this.state.value가 되고 React state는 single source of truth 가 됩니다. React state를 업데이트하기 위해 입력값이 변경될 때마다 handleChange가 동작하기 때문에 사용자가 입력할 때 보여지는 값이 업데이트됩니다.
제어 컴포넌트로 사용하면 input의 값은 항상 React state에 의해 결정됩니다. 다른 UI엘리먼트에 input의 값을 전달하거나 다른 이벤트 핸들러에 값을 재설정할 수 있습니다.
textarea 태그
HTML에서 <textarea> 엘리먼트는 텍스트를 자식의로 정의합니다.
그러나 React네서는 value 어트리뷰트를 대신 사용해 <input>과 비슷하게 작성할 수 있습니다.
class EssayForm extends React.Component { constructor(props) { super(props); this.state = {value: 'Please write an essay about your favorite DOM element.'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('An essay was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <textarea type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }
select 태그
HTML에서 <select>는 드롭 다운 목록을 만듭니다.
<select> <option selected value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select>
React에서는 selected 어트리뷰트 대신 최상단 select 태그에 value 어트리뷰트를 사용합니다. 한 곳에서 업데이트만 하면되기 때문에 제어 컴포넌트에서 사용하기 더 편합니다.
class FlavorForm extends React.Component { constructor(props) { super(props); this.state = {value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Pick your favorite flavor: <select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </label> <input type="submit" value="Submit" /> </form> ); } }
select 태그에 multiple 옵션을 허용한다면 value 어트리뷰트에 배열을 전달할 수 있습니다.
<select multiple={true} value={['B', 'C']}>
file input 태그
vlaue가 읽기 전용이기 때문에 React에서는 비제어 컴포넌트로 분류됩니다.
다중 입력 제어하기
여러 input 엘리먼트를 제어해야할 때 각 엘리먼트에 name 어트리뷰트를 추가하고 evnt.target.name 값을 통해 핸들러가 어떤 작업을 할 지 선택할 수 있게 해줍니다.
class Reservatio extends React.Component { constructor(props) { super(props); this.state = { isGoing: true, numberOfGuests: 2 }; this.handleInputChange = this.handleInputChange.bind(this); } handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }); } render() { return ( <form> <label> Is going: <input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange} /> </label> <br /> <label> Number of guests: <input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange} /> </label> </form> ) } }
제어되는 input Null 값
제어 컴포넌트에 value prop을 지정하면 의도하지 않는 한 사용자가 변경할 수 없습니다. value를 설정했는데 여전히 수정할 수 있다면 실수로 vlaue를 undefined나 null로 설정했을 수 있습니다.
ReactDOM.render(( <input value="hi" /> ),document.getElementById('root') ); setTimeout(function() { ReactDOM.render(<input value={null} />, document.getElementById('root')); }, 1000);
처음 렌더링한 input은 입력이 잠겨있지만 1초 후 렌더링된 input은 입력이 가능해집니다.
제어 컴포넌트의 대안
데이터를 변경할 수 있는 모든 방법에 대해 이벤트 핸들러를 작성하고 React 컴포넌트를 통해 모든 입력 상태를 연결해야 하기 때문에 제어 컴포넌트를 사용하는게 지루할 수 있는데 이 때 입력 폼을 구현하기 위한 대체 기술인 비제어 컴포넌트를 사용할 수 있습니다.
728x90'IT > 리액트' 카테고리의 다른 글
리액트 주요개념 - 합성 vs 상속 (0) 2022.01.16 리액트 주요개념 - State 끌어올리기 (0) 2022.01.16 리액트 주요개념 - 리스트와 key (0) 2022.01.16 리액트 주요개념 - 조건부 렌더링 (0) 2022.01.16 리액트 주요개념 - 이벤트 처리하기 (0) 2022.01.15