[React] 리액트 Form의 특징과 종류 - 제어 컴포넌트

    Form과 Controlled Component


    Form

    사용자로부터 입력을 받기 위해 사용하는 것이다.

     

    리액트 Form VS. HTML Form

    리액트는 컴포넌트 내부에서 state를 통해 데이터를 관리하는 반면,

    HTML은 Element 내부에 각각의 state가 존재한다.

     

    📌 예제1-1. HTML Form

    <form>
    	<label>
        	이름:
            <input type="text" name="name" />
        </label>
        <button type="submit">제출</button>
    </form>

     

    HTML Form은, 자바스크립트를 이용해 사용자가 입력한 값이 접근하기에는 힘든 구조이다.

    Controlled Component(리액트)를 이용하여 웹 페이지를 제작한다.

     

    Controlled component

    사용자가 입력한 값에 접근하고, 제어할 수 있도록 하는 컴포넌트를 의미한다.

    즉, 값이 리액트에 의해서 통제(접근 및 제어)를 받는 Input Form Element를 의미한다. 

     

    HTML Form VS. Controlled Component

     

     

    HTML Form은 자체적으로 state를 관리하므로, 태그가 각 내부에 state를 가지고 있다.

    반면, Controlled Component를 사용하면 모든 입력값이 리액트의 state를 통해 관리된다.

    즉, Controlled Component는 리액트에서 모든 값을 통제할 수 있는 구조를 가지고 있다.

     

    📌 예제1-2. 예제 1-1을 Controlled Component로 변환

    function NameForm(props) {
      const [value, setValue] = useState("");
    
      const handleChange = (event) => {
        setValue(event.target.value);
      }
    
      const handleSubmit = (event) => {
        alert('입력한 이름: ', value);
        event.preventDefault();
      }
    
      return(
        <form onSubmit={handleSubmit}>
          <label>
            이름:
            <input type="text" value={value} onChange={handleChange} />
          </label>
          <button type="submit">제출</button>
        </form>
      )
    
    }

     

    Controlled Component를 사용하면,

    입력값이 리액트의 state를 통해 관리되며 사용자의 입력을 직접적으로 제어할 수 있다.

    ✅ 즉, 여러 개의 입력 양식의 값을 원하는 대로 조정할 수 있다.

    • 입력 양식의 초기값을 내가 원하는 대로 넣어줄수 있으며,
    • 다른 양식의 값이 변경되었을 때 또 다른 양식의 값도 자동적으로 변경해줄 수 있다.

     

    📌 예제2. 모든 입력값을 대문자로 변경

    const handleChange = (event) => {
      setValue(event.target.value.toUpperCase())
    }

     

     

     

    다양한 Forms


    Textarea

    📌 (HTML) textarea 태그

    <textarea>
      안녕하세요,여기에 이렇게 텍스트가 들어가게 됩니다!
    </textarea>

    HTML에서는 textarea의 자식으로 텍스트가 들어가는 반면,

    리액트는 textarea에 value attribute를 사용하여 텍스트를 표시하게 된다.

     

     

    📌 (React) textarea 태그

    function RequestForm() {
      const [value, setValue] = useState("요청사항을 입력하세요.")
    
      const handleChange = (event) => {
        setValue(evnet.target.value);
      }
    
      const handleSubmit = (event) => {
        alert('입력한 요청사항: ' +  value)
        event.preventDefault();
      }
    
      return (
        <form onSubmit={handleSubmit}>
          <label>
            요청사항 : 
            <textarea value={value} onChange={handleChange}></textarea>
          </label>
          <button></button>
    
        </form>
      )
    }

     

    Select

    Drop-down 목록을 보여주기 위한 HTML 태그이다.

    Drop-down은 여러 개의 옵션 중에 하나를 선택할 수 있는 기능을 제공한다.

     

    📌 (HTML) select 태그

    <select>
      <option value="apple">사과</option>
      <option value="banana">바나나</option>
      <option selected value="grape">포도</option>
      <option value="watermelon">수박</option>
    </select>

     

    HTML에서는 현재 선택된 옵션 'selectd' 속성을 부여한다.

    반면, React에서는 selected 속성을 사용하는 대신 
    <select> 태그에 value attribute를 사용하여 선택된 옵션을 표시한다.

     

     

    📌 (React) select 태그

    function Fruitselect(props) {
      const [value, setValue] = useState("grape");
    
      const handleChange = (event) => {
        setValue(event.target.value);
      }
    
      const handleSubmit = (event) => {
        alert('선택한 과일: ' +  value);
        event.preventDefault();
      }
    
      return(
        <form onSubmit={handleSubmit}>
          <label>
            과일을 선택하세요:
            <select value={value} onChange={handleChange}>
              <option value="apple">사과</option>
              <option value="banana">바나나</option>
              <option value="grape">포도</option>
              <option value="watermelon">수박</option>
            </select>
          </label>
          <button type="submit">제출</button>
        </form>
      )
    }

     

     

    목록에서 다중으로 선택되도록 하려면 아래와 같이 코드를 작성한다.

    • <select> 태그 안에 multipe={true}를 작성하고,
    • value attribute에는 선택된 옵션의 값이 들어있는 배열을 넣어준다.
    <select multiple={true} value={['B', 'C']}></select>

     

    Summary

    // input 태그
    <input type="text" value={value} onChange={handleChange}/>
    
    // textarea 태그
    <textarea value={value} onChange={handleChange}/>
    
    // select 태그
    <select value={value} onChange={handleChange}>
      <option value="apple">사과</option>
      <option value="banana">바나나</option>
      <option value="grape">포도</option>
      <option value="watermelon">수박</option>
    </select>

     

    input, textarea, select 태그를 모두 Controlled Component로 만드는 방법은 비슷하다.

    1. value attribute를 통해서 값을 전달하고, 
    2. 값을 변경할 때에는 onChange에서 setValue()를 사용하여 값을 업데이트

    이러한 방식은 실제로 사용자 입력을 받는 컴포넌트를 만들 때 사용한다.

     

    File input

    디바이스의 저장 장치로부터 하나 또는 여러 개의 파일을 선택할 수 있게 해주는 HTML 태그이다.

    📌 (HTML) file input 태그

    <input type="file" />

    file input 태그는 그 값이 읽기 전용이기 때문에, React에서는 Uncontrolled Component로 구분된다. 

     즉, 값이 리액트의 통제를 받지 않는다.
     
     
     

     

    Multiple inputs

    하나의 컴포넌트에서 여러 개의 입력을 다루기 위해서는,

    여러 개의 state를 선언하여 각각의 입력에 대해 사용한다.

     
    📌 예제3. 호텔 예약 Form - 여러 개의 입력값 받기
    function Reservation(props) {
      const [haveBreakfast, setHaveBreakfast] = useState(true);
      const [numberOfGuest, setNumberOfGuest] = useState(2);
    
      const handleSubmit = (event) => {
        alert(`아침식사 여부: ${haveBreakfast}, 방문객 수: ${numberOfGuest}`);
        event.preventDefault();
      }
    
      return(
        <form onSubmit={handleSubmit}>
          <label>
            아침식사 여부:
            <input 
              type="checkbox"
              checked={haveBreakfast}
              onChange={(event) => {
                setHaveBreakfast(event.target.checked)
              }} />
          </label>
          <label>
            방문객 수:
            <input 
              type="number"
              value={numberOfGuest}
              onChange={(event) => {
                setNumberOfGuest(event.target.value)
              }} />
          </label>
          <button type="submit">제출</button>
        </form>
      )
    }

    클래스 컴포넌트에서는 setState() 하나로 모든 state를 업데이트했지만,

    함수 컴포넌트는 각 state의 변수마다 'set-' 함수가 따로 존재한다.

    그러므로, 함수 컴포넌트에서는 각각의 set 함수를 사용해서 값을 구현 및 업데이트한다.

     

    Input null value

    제어 컴포넌트에 value를 정해진 값으로 넣으면, 수정하지 않는 한 입력값을 바꿀 수 없다.

    그러므로 value를 넣되, 자유롭게 입력할 수 있도록 하고 싶다면 값에 'undefined' 또는'null'을 넣어준다.

     

    📌 Input null value 

    ReactDOM.render(<input value="hi" />, rootNode)
    
    // 값을 바꿀수 없는 입력 불가상태
    
    setTimeout(function() {
      ReactDOM.render(<input value={null} />, rootNode)
    }, 1000)
    
    // 타이머에 의해 입력 가능한 상태로 바뀜


    🚀 참고

    댓글