React : 입력 폼
by 담담이담HTML과 다른 점
1) onChange
리액트에선 순수 HTML과 다르게
onChange Prop을 사용하면 입력 값이 바뀔 때마다 핸들러 함수를 실행한다.
html의 oninput 이벤트와 같다고 생각하면 된다.
리액트 개발자들은 주로 onChange 라는 Prop을 사용한다.
2) htmlFor
<label /> 태그에서 사용하는 속성인 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(); // ... }
제어 컴포넌트
인풋 태그의 value 속성을 지정하고 사용하는 컴포넌트다.
리액트에서 인풋의 값을 제어하는 경우로
리액트에서 지정한 값과 실제 인풋 value의 값이 항상 같다.
이렇게 하면 값을 예측하기가 쉽고
인풋에 쓰는 값을 여러 군데서 쉽게 바꿀 수 있다는 장점이 있어서
리액트에서 권장하는 방법이다.
이때 State냐 Prop이냐는 중요하지 않고,
리액트로 value를 지정한다는 것이 핵심이다.
아래 두 경우 모두 제어 컴포넌트이다.
예시 1
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> ) }
예시 2
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> ) }
비제어 컴포넌트
인풋 태그의 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); // ... }
만약 이렇게 제어 컴포넌트랑 비제어 컴포넌트 모두 쓸 수 있는 경우라면
제어 컴포넌트를 사용하는 걸 추천한다.
하지만 반드시 비제어 컴포넌트로 만들어야만 하는 경우가 있다.
대표적으로 파일을 선택하는 인풋이 그렇다.

블로그의 정보
유명한 담벼락
담담이담