HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에, React의 다른 DOM 엘리먼트와 다르게 동작한다.
JavaScript 함수로 폼의 제출을 처리하고 사용자가 폼에 입력한 데이터에 접근하도록 하려면 '제어 컴포넌트 (controlled components)'라는 기술을 이용해야 한다.
<input>
, <textarea>
, <select>
와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트form 태그를 사용했을 때 HTML과 React 둘 다 값을 관리하게 된다.
이것을 신뢰 가능한 단일 출처 (single source of truth)로 만들어 두 요소를 결합해야 하며,
이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 제어 컴포넌트 (controlled component)라고 한다.
<input>
, <textarea>
, <select>
와 같은 폼 엘리먼트의 value 어트리뷰트를 React state 값으로 설정한다.
export default function SimpleForm(){
const [nickname, setNickName] = useState('');
const handleChange = (e) => {
setNickName(e.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
alert(nickname);
}
return(
<form onSubmit = {handleSubmit} >
<label>닉네임 : </label>
/* ↓ value={ React state } */
<input type="text" name="nickname" onChange={handleChange} value={nickname} />
<input type="submit" value="제출"/>
</form>
);
}
여러 input 엘리먼트를 제어해야할 때, 각 엘리먼트에 name 어트리뷰트를 추가하고 event.target.name 값을 통해 핸들러가 어떤 작업을 할 지 선택할 수 있게 한다.
export default function SimpleForm(){
const [nickname, setNickName] = useState('');
const [password, setPassWord] = useState('');
const handleChange = (e) => {
/* event.target.name 값을 통해 선택 */
if(e.target.name === 'nickname') setNickName(e.target.value);
else setPassWord(e.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
alert(`nickname : ${nickname}, password : ${password}`);
}
return(
<form onSubmit = {handleSubmit} >
<label>닉네임 : </label>
<input type="text" name="nickname" onChange={handleChange} value={nickname} />
<br />
<label>패스워드 : </label>
<input type="text" name="password" onChange={handleChange} value={password} />
<input type="submit" value="제출"/>
</form>
);
}
ES6의 객체 초기자(computed property name) 구문 사용 - setState({ [name] : value });
export default function SimpleForm(){
const [userInputs, setUserInputs] = useState({
nickname : '',
password : '',
});
const handleChange = (e) => {
/* event.target.name 값을 통해 선택 */
setUserInputs({...userInputs, [e.target.name] : e.target.value});
}
const handleSubmit = (e) => {
e.preventDefault();
const { nickname, password } = userInputs;
alert(`nickname : ${nickname}, password : ${password}`);
}
return(
<form onSubmit = {handleSubmit} >
<label>닉네임 : </label>
<input type="text" name="nickname" onChange={handleChange} value={userInputs.nickname} />
<br />
<label>패스워드 : </label>
<input type="text" name="password" onChange={handleChange} value={userInputs.password} />
<input type="submit" value="제출"/>
</form>
);
}