ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리액트 주요개념 - 폼
    IT/리액트 2022. 1. 16. 01:32
    728x90

    제어 컴포넌트 (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를 undefinednull로 설정했을 수 있습니다.

    ReactDOM.render((
      <input value="hi" />
      ),document.getElementById('root')
    );
    
    setTimeout(function() {
      ReactDOM.render(<input value={null} />, document.getElementById('root'));
    }, 1000);

    처음 렌더링한 input은 입력이 잠겨있지만 1초 후 렌더링된 input은 입력이 가능해집니다.

     

     

    제어 컴포넌트의 대안

    데이터를 변경할 수 있는 모든 방법에 대해 이벤트 핸들러를 작성하고 React 컴포넌트를 통해 모든 입력 상태를 연결해야 하기 때문에 제어 컴포넌트를 사용하는게 지루할 수 있는데 이 때 입력 폼을 구현하기 위한 대체 기술인 비제어 컴포넌트를 사용할 수 있습니다.

    728x90

    댓글

Designed by Tistory.