본문 바로가기

React

React 시작하기 - 09 - textarea, input, select 등 폼 form 태그 다루기

사용자로부터 값을 입력받는 form 태그는 자주 사용한다.

textarea, input select 등 여러 태그가 있다.

리액트에서는 이러한 form 태그를 쉽게 다룰 수 있도록 만들어 놓았다.

특히 value 를 번거롭게 다루지 않고 손쉽게 다룰 수 있도록 해 두었다.

<body>
    
    <div id="root1">
    </div>
    <div id="border1"></div>
    
    <div id="root2">
    </div>
    <div id="border2"></div>

    <textarea id="ta">
    </textarea>

    <div id="root3">
    </div>
    <div id="border3"></div>

    <div id="root4">
    </div>
    <div id="border4"></div>


    <div id="root5">
    </div>
    <div id="border5"></div>



    <!-- react cdn -->
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <!-- react dom cdn -->
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <!-- babel cdn -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <!-- define type as a babel  -->
    <script type="text/babel">
        class MakeBorder extends React.Component {
            render() {
                return <p>--------------------------------root{this.props.num}----------------------------</p>;
            }
        }
    
        // 리액트가 form 요소를 비롯하여 다양한 사용자 입력 태그들을 어떻게 다루는지 알아보자.

        // 제어 컴포넌트 (Controlled Component)
        // 제어 컴포넌트는 리액트가 관리하고 제어하는 컴포넌트를 말한다.
        // 리액트가 컴포넌트의 무엇을 관리하고 무엇을 제어한다는 말인가?
        // 사용자가 입력하는 입력값들을 리액트가 관리하며, 컴푸넌트에 발생하는 입력과 츨력을 관리한다. 
        // 컴포넌트 안에서 모든 값들이 결국 리액트의 staate 로 모이고, state로부터 나온다.
        // 예를 들어 아래 컴포넌트를 보자
        class NameForm extends React.Component {
            constructor(props) {
                super(props);
                this.state = {val: ''};
                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);
            }

            handleChange(e) {
                console.log('------------------------------');
                console.log('change > val');
                console.log(e.target.value);
                console.log('state > val');
                console.log(this.state.val);
                if(this.props.isControl) {
                    this.setState({val: e.target.value});
                }
            }

            handleSubmit(e) {
                e.preventDefault();
                console.log('------------------------------');
                console.log('submit > val');
                console.log(e.target.querySelector('input[type="text"]').value);
                console.log('state > val');
                console.log(this.state.val);
            }

            render() {
                return (
                    <form  onSubmit={this.handleSubmit}>
                        <input type="text" value={this.state.val} onChange={this.handleChange} />
                        <input type="submit" value="click to submit" />
                    </form>
                );
            }
        }

        ReactDOM.render( <NameForm isControl={true}/>, document.getElementById('root1') );
        ReactDOM.render( <MakeBorder num="1" />, document.getElementById('border1') );
        // 총 세 곳에서 state를 주거나 받는다.
        // 첫째는 사용자가 폼을 조작할 수 있는 input 태그다.
        // 둘째는 사용자가 input 태그를 조작했을 때 발생하는 이벤트 핸들러다.
        // input 태그 ===> 이벤트 핸들러 ===> 리액트 state
        // 리액트 state ===> input 태그
        // input:text 태그에서 value={this.state.val} 가 없다면 어떻게 될까.
        // value 값을 리액트 state로부터 받아오는 값이 아니므로 컴포넌트가 들고 있는 값이랑 시용자가 화면에서 보는 값이랑 다를 수 있다.
        // 이벤트 핸들러에서 this.setState({val: e.target.value}); 가 없다면 어떻게 될까.
        // 사용자가 입력한 값이 리액트 state의 값을 바꾸지 못하므로 해당 값을 불러다 쓰는 곳들에서 변화가 없는 것처럼 보인다.
        // input:text에 value={this.state.val} 를 설정해 두었다면 화면상 값이 변하지 않고, 설정하지 않았다면 화면상으로는 변해도 내부적으로 state값은 변하지 않았음을 input:submit으로 알 수 있다.
        ReactDOM.render( <NameForm isControl={false}/>, document.getElementById('root2') );
        ReactDOM.render( <MakeBorder num="2" />, document.getElementById('border2') );



        // textarea 태그
        // html 에서는 textarea가 text를 자식 노드로 가지고 있다.
        document.getElementById('ta').childNodes[0].data="check the child node type of this text";
        // 리액트에서는 textarea에 value라는 속성을 대신 넣어준다.
        class EssayForm extends React.Component {
            constructor(props) {
                super(props);
                this.state={val:''}
                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);

            }

            handleChange(e) {
                console.log('input');
                console.log(e.target.value);
                this.setState({val: e.target.value})
                console.log('state');
                console.log(this.state.val);
            }

            handleSubmit(e) {
                e.preventDefault();
                console.log('state');
                console.log(this.state.val);
            
            }

            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        <textarea cols="30" rows="10" value={this.state.val} onChange={this.handleChange}></textarea>
                        <input type="submit" value="click to submit" />
                    </form>
                );
            }
        }

        ReactDOM.render( <EssayForm />, document.getElementById('root3') );
        ReactDOM.render( <MakeBorder num="3" />, document.getElementById('border3') );



        // select 태그
        // html에서 select 태그는 드롭다운 목록을 만든다. 
        // 예를 들어 아래 select 태그는 사용자가 과일 목록을 선택할 수 있도록 만든다.
        // <select>
        //     <option value="grapefruit">Grapefruit</option>
        //     <option value="lime">Lime</option>
        //     <option selected value="coconut">Coconut</option>
        //     <option value="mango">Mango</option>
        // </select>
        // 초기값은 selected 속성이 들어 있는 coconut 항목이다.
        // 사용자가 값을 선택하면 그 option 태그에 selected 속성이 추가된다.
        // html 에서는 선택한 값에 접근하려면 select 하위 속성인 option 요소들 중에서 selected 속성이 있는 요소를 골라내야 한다.
        // 리액트에서는 option 태그에 있는 selected 속성을 사용하지 않는다.
        // 대신 리액트에서는 select 태그 자체에 value 라는 속성을 사용한다.
        class FlavorForm extends React.Component {
            constructor(props) {
                super(props);
                this.state = {val: ''};
                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);
            }

            handleChange(e) {
                console.log('input > val');
                console.log(e.target.value);
                this.setState({val: e.target.value})
                console.log('state > val');
                console.log(this.state.val);
            }

            handleSubmit(e) {
                e.preventDefault();
                console.log('state > val');
                console.log(this.state.val);

            }

            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        <select value={this.state.val} onChange={this.handleChange}>
                            <option value="grapefruit">Grapefruit</option>
                            <option value="lime">Lime</option>
                            <option value="coconut">Coconut</option>
                            <option value="mango">Mango</option>
                        </select>
                        <input type="submit" value="click here to submit" />
                    </form>
                );
            }
        }

        ReactDOM.render( <FlavorForm />, document.getElementById('root4') );
        ReactDOM.render( <MakeBorder num="4" />, document.getElementById('border4') );


        // 다중 입력 제어하기.
        // 리액트 컴포넌트에서 여러 input 엘리먼트를 제어해야 하는 경우가 있다.
        // 각 엘리먼트에 name 속성을 추가해 두고 그 값에 따라 핸들러가 다른 처리를 하도록 만들 수도 있다.
        class Reservation extends React.Component {
            constructor(props) {
                super(props);
                this.state = {isFamily: false, numberOfGuests: 0};
                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);
            }

            handleChange(e) {
                let val;
                if(e.target.name == 'family') {
                    console.log('family > val');
                    val = {isFamily: e.target.checked};
                } else if(e.target.name == 'num') {
                    console.log('num > val');
                    val = {numberOfGuests: e.target.value};
                } else {
                    console.log('unknown > val');
                    val = {isFamily: false, numberOfGuests:0};
                }
                this.setState(val);
                console.log('state > val');
                console.log(this.state);
            }

            handleSubmit(e) {
                e.preventDefault();
                console.log('state > val');
                console.log(this.state);
            }

            render() {

                return (
                    <form onSubmit={this.handleSubmit}>
                        <label>
                            Is Family Guest: 
                            <input type="checkbox" name="family" checked={this.state.isFamily} onChange={this.handleChange} />
                        </label>
                        <br />
                        <label>
                            Number of Guests: 
                            <input type="number" name="num" value={this.state.numberOfGuests} onChange={this.handleChange} />
                        </label>
                        <input type="submit" value="click to submit" />
                    </form>
                );


            }
        }

        ReactDOM.render( <Reservation />, document.getElementById('root5') );
        ReactDOM.render( <MakeBorder num="5" />, document.getElementById('border5') );

        // 덧붙임 - ES6 문법: 객체 key 값에 변수값 넣기
        let result = {hello: 'world'};
        // 위와 같은 객체를 만들려고 할 때, key 값에 들어가야 하는 값을 다른 변수가 들고 있다면 쉽게 하는 방법이 있다.
        let keyVal = 'hello';
        result = {};
        result[keyVal] = 'world';
        // 위는 ES5 문법이다.
        // 더 간단하게 만들 수 있도록 ES6부터는 아래와 같은 문법도 가능해졌다.
        result = {[keyVal]: 'world'};
            
    </script>
</body>

- 220601 

 

참고자료 -

https://ko.reactjs.org/docs/forms.html

반응형