- React에서 HTML form 요소는 내부 상태를 갖고 있기 때문에 다른 DOM 요소들과 다르게 동작함
- form의 제출을 처리하고, 폼에 입력된 데이터에 대해 접근하기 위해 controlled component를 사용함
Controlled Component
- HTML에서
<input>
, <textarea>
, <select>
와 같은 form 요소는 자신의 상태를 가지고, 그 상태는 사용자의 입력에 기반하여 갱신됨
- React에서 변경 가능한 상태는 컴포넌트의
state
프로퍼티에 저장되고, setState()
에 의해 갱신됨
- React 상태를 single source of truth로 만듬으로써 위의 둘을 결합할 수 있음
- single source of truth for each state
- 컴포넌트는 각각 고유한 상태를 가질 수 있음
- 컴포넌트들 간 상태를 공유하고 싶다면, 그들의 공통 부모 컴포넌트로 상태를 끌어 올림
- form을 렌더링하는 React 컴포넌트는 사용자 입력에 의해 form에서 무엇이 일어나는지 제어함
- React에 의해 값이 제어되는 input form 요소를 controlled component라 부름
export default function NameForm() {
const [name, setName] = useState('');
const handleChange = ({target}) => {
setName(target.value);
}
const handleSubmit = (event) => {
alert('A name was submitted: ' + name);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
- 위 예시 설명
- form 요소에
value
속성을 설정했기 때문에, 보이는 값은 항상 this.state.value
가 됨
- 키보드를 칠 때 마다 React의 상태를 갱신하기 위해
hanldeCange
실행되기 때문에, 사용자가 타자를 칠 때 마다 보이는 값이 갱신됨
- controlled component로 사용하면, input 값은 항상 React 상태에 의해 결정됨
- input 값을 다른 UI 요소에게 전달하거나, 다른 이벤트 헨들러에서 input 값을 재설정할 수 있음
textarea 태그
- HTML에서
<textarea>
요소는 자식 요소에 의해 텍스트가 정의됨
- React에서
<textarea>
는 value
속성을 사용함
- 이렇게 하면
<textarea>
를 사용하는 form을 한 줄 입력을 사용하는 form과 비슷하게 작성할 수 있음
export default function EssayForm() {
const [textValue, setTextValue] = useState("");
const handleTextChange = ({target}) => setTextValue(target.value);
return (
<form>
<label>
Essay:
<textarea value={textValue} onChange={handleTextChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
select 태그
- HTML에서
<select>
는 drop-down list를 생성함
selected
속성을 사용하여 초기에 선택되도록 설정함
- React에서는
selected
속성을 사용하는 대신 최상단 select
태그에 value
속성을 사용함
- 최상단
select
태그의 value
속성만 갱신하면 되기 때문에 휠씬 편리함
export default function FlavorForm() {
const [textValue, setTextValue] = useState("");
const handleTextChange = ({target}) => setTextValue(target.value);
return (
<form>
<label>
Pick your favorite flavor:
<select value={textValue} onChange={handleTextChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
<select>
의 value
속성에 배열을 전달해서 여러 개의 옵션을 선택할 수 있음
<select multiple={true} value={['B', 'C']}>
<input type="text">
, <textarea>
, <select>
모두 비슷하게 동작함
- 제어 컴포넌트를 구현할 때,
value
속성을 허용함
- 여러 개의 controlled
input
요소를 처리할 때
- 각 요소에
name
속성을 추가함
- event handler 함수가
event.target.name
의 값을 통해 무엇을 할지 선택함
export default function Reservation() {
const [reservationInfo, setReservationInfo] = useState({
isGoing: true,
numberOfGuests: 2,
});
const handleInputChange = ({target}) => {
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
setReservationInfo({
...ReservationInfo,
[name]: value
});
};
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={reservationInfo.isGoing}
onChange={handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={reservationInfo.numberOfGuests}
onChange={handleInputChange} />
</label>
</form>
);
}
- ES6의
computed property name
을 사용하여 주어진 input name에 대응하는 상태 키의 값을 갱신함
setReservationInfo({
...ReservationInfo,
[name]: value
});
- HTML에서
<input type="file">
는 사용자가 그들의 저장장치로부터 서버에 하나 이상의 파일을 업로드하거나 File API
를 통해서 JavaScript를 사용하여 조작할 수 있게 함
- file input의 값은 읽기 전용이므로, React에서 file input은 uncontrolled component임
<input type="file" />