리액트에선 순수 HTML과 다르게
onChange Prop을 사용하면 입력 값이 바뀔 때마다 핸들러 함수를 실행
oninput 이벤트와 같다고 생각하시면 된다.
리액트 개발자들은 주로 onChange 라는 Prop을 사용
태그에서 사용하는 속성인 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>
)
}
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이 그렇다.