React_27_입력폼 정리하기

지원·2023년 10월 10일

React

목록 보기
28/71
post-thumbnail

HTML와 다른점

onChange

리액트에선 순수 HTML과 다르게
onChange Prop을 사용하면 입력 값이 바뀔 때마다 핸들러 함수를 실행

oninput 이벤트와 같다고 생각하시면 된다.
리액트 개발자들은 주로 onChange 라는 Prop을 사용

htmlFor

태그에서 사용하는 속성인 for 는 자바스크립트 반복문 키워드인 for 와 겹치기 때문

리액트에서는 htmlFor 를 사용

폼을 다루는 기본적인 방법

스테이트를 만들고 target.value 값을 사용해서 값을 변경해 줄 수 있다.
이때 value Prop으로 스테이트 값을 내려주고,
onChange Prop으로 핸들러 함수를 넘겨준다.

function TripSearchForm() {
  const [location, setLocation] = useState('Seoul');
  const [checkIn, setCheckIn] = useState('2022-01-01');
  const [checkOut, setCheckOut] = useState('2022-01-02');

  const handleLocationChange = (e) => setLocation(e.target.value);

  const handleCheckInChange = (e) => setCheckIn(e.target.value);

  const handleCheckOutChange = (e) => setCheckOut(e.target.value);
  
  return (
    <form>
      <h1>검색 시작하기</h1>
      <label htmlFor="location">위치</label>
      <input id="location" name="location" value={location} placeholder="어디로 여행가세요?" onChange={handleLocationChange} />
      <label htmlFor="checkIn">체크인</label>
      <input id="checkIn" type="date" name="checkIn" value={checkIn} onChange={handleCheckInChange} />
      <label htmlFor="checkOut">체크아웃</label>
      <input id="checkOut" type="date" name="checkOut" value={checkOut} onChange={handleCheckOutChange} />
      <button type="submit">검색</button>
    </form>
  )
}

폼 값을 객체 하나로 처리하기

이벤트 객체의 target.name 과 target.value 값을 사용해서 값을 변경해 줄 수 있다.

이렇게하면 객체형 스테이트 하나만 가지고도 값을 처리할 수 있다.

function TripSearchForm() {
  const [values, setValues] = useState({
    location: 'Seoul',
    checkIn: '2022-01-01',
    checkOut: '2022-01-02',
  })

  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues((prevValues) => ({
      ...prevValues,
      [name]: value,
    }));
  }
    
  return (
    <form>
      <h1>검색 시작하기</h1>
      <label htmlFor="location">위치</label>
      <input id="location" name="location" value={values.location} placeholder="어디로 여행가세요?" onChange={handleChange} />
      <label htmlFor="checkIn">체크인</label>
      <input id="checkIn" type="date" name="checkIn" value={values.checkIn} onChange={handleChange} />
      <label htmlFor="checkOut">체크아웃</label>
      <input id="checkOut" type="date" name="checkOut" value={values.checkOut} onChange={handleChange} />
      <button type="submit">검색</button>
    </form>
  )
}

기본 submit 동작 막기

HTML 폼의 기본 동작은 submit 타입의 버튼을 눌렀을 때 페이지를 이동하는 것.

이벤트 객체의 preventDefault 를 사용하면 이 동작을 막을 수 있다.

const handleSubmit = (e) => {
  e.preventDefault();
  // ...
}

제어 컴포넌트

input 태그의 value 속성을 지정하고 사용하는 컴포넌트

리액트에서 input의 값을 제어하는 경우로
리액트에서 지정한 값과 실제 input value 의 값이 항상 같다.

이렇게 하면 값을 예측하기가 쉽고 input에 쓰는 값을
여러 군데서 쉽게 바꿀 수 있다는 장점이 있어서 리액트에서 권장하는 방법

이때 State냐 Prop이냐는 중요하지 않고, 리액트로 value 를 지정한다는 것이 핵심

function TripSearchForm() {
  const [values, setValues] = useState({
    location: 'Seoul',
    checkIn: '2022-01-01',
    checkOut: '2022-01-02',
  })

  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues((prevValues) => ({
      ...prevValues,
      [name]: value,
    }));
  }
    
  return (
    <form>
      <h1>검색 시작하기</h1>
      <label htmlFor="location">위치</label>
      <input id="location" name="location" value={values.location} placeholder="어디로 여행가세요?" onChange={handleChange} />
      <label htmlFor="checkIn">체크인</label>
      <input id="checkIn" type="date" name="checkIn" value={values.checkIn} onChange={handleChange} />
      <label htmlFor="checkOut">체크아웃</label>
      <input id="checkOut" type="date" name="checkOut" value={values.checkOut} onChange={handleChange} />
      <button type="submit">검색</button>
    </form>
  )
}
function TripSearchForm({ values, onChange }) {
  return (
    <form>
      <h1>검색 시작하기</h1>
      <label htmlFor="location">위치</label>
      <input id="location" name="location" value={values.location} placeholder="어디로 여행가세요?" onChange={onChange} />
      <label htmlFor="checkIn">체크인</label>
      <input id="checkIn" type="date" name="checkIn" value={values.checkIn} onChange={onChange} />
      <label htmlFor="checkOut">체크아웃</label>
      <input id="checkOut" type="date" name="checkOut" value={values.checkOut} onChange={onChange} />
      <button type="submit">검색</button>
    </form>
  )
}

비제어 컴포넌트

input 태그의 value 속성을 리액트에서 지정하지 않고 사용하는 컴포넌트

function TripSearchForm({ onSubmit }) {
  return (
    <form onSubmit={onSubmit} >
      <h1>검색 시작하기</h1>
      <label htmlFor="location">위치</label>
      <input id="location" name="location" placeholder="어디로 여행가세요?" />
      <label htmlFor="checkIn">체크인</label>
      <input id="checkIn" type="date" name="checkIn" />
      <label htmlFor="checkOut">체크아웃</label>
      <input id="checkOut" type="date" name="checkOut" />
      <button type="submit">검색</button>
    </form>
  )
}

위처럼 작성해도 onSubmit 함수에서는 폼 태그를 참조할 수 있다.

값들을 참조하려면 이벤트 객체의 target 활용해서 할 수도 있고

const handleSubmit = (e) => {
  e.preventDefault();
  const form = e.target;
  const location = form['location'].value;
  const checkIn = form['checkIn'].value;
  const checkOut = form['checkOut'].value;
  // ....
}

폼 태그로 곧바로 FormValue 를 바로 만드는 것도 가능하다.

const handleSubmit = (e) => {
  e.preventDefault();
  const form = e.target;
  const formValue = new FormValue(form);
  // ...
}

만약 이렇게 제어 컴포넌트랑 비제어 컴포넌트 모두 쓸 수 있는 경우
제어 컴포넌트를 사용하는 걸 추천

하지만 반드시 비제어 컴포넌트로 만들어야만 하는 경우가 있다,
대표적으로 파일을 선택하는 input이 그렇다.

0개의 댓글