2023.02.01 폼
폼은 사용자로부터 입력을 받기 위해 사용하는 것입니다.
HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에,
React의 다른 DOM 엘리먼트와 다르게 동작합니다.
예를 들어, 순수한 HTML에서 이 폼은 name을 입력받습니다.
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
이 폼은 사용자가 폼을 제출하면 새로운 페이지로 이동하는 기본 HTML 폼 동작을 수행합니다.
React에서 동일한 동작을 원한다면 그대로 사용하면 됩니다.
그러나 대부분의 경우, JavaScript 함수로 폼의 제출을 처리하고 사용자가 폼에 입력한 데이터에 접근하도록 하는 것이 편리합니다.
이를 위한 표준 방식은 “제어 컴포넌트 (controlled components)“라고 불리는 기술을 이용하는 것입니다.
사용자가 입력한 값에 접근하고 제어할 수 있도록 해주는 컴포넌트입니다.
제어 컴포넌트는 그 값이 리액트의 통제를 받는 입력 폼 엘리먼트(input form element)를 의미
HTML에서 <input>, <textarea>, <select>와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트합니다.
React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트됩니다.
우리는 React state를 “신뢰 가능한 단일 출처 (single source of truth)“로 만들어 두 요소를 결합할 수 있습니다.
그러면 폼을 렌더링하는 React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어합니다.
이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 “제어 컴포넌트 (controlled component)“라고 합니다.
예를 들어, 이전 사용자의 이름을 입력 받는 HTML 폼을 리액트의 제어 컴포넌트로 만들면 아래와 같습니다.
import { useState } from "react";
function NameForm(props) {
const [Value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value);
}
const handleSubmit = (event) => {
alert('입력한 이름: ' + value);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={value} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
위의 코드에서 <input> 태그의 value={value} 부분을 볼 수 있는데
리액트 컴포넌트의 state에서 값을 가져다 넣어 주는 것입니다.
그래서 항상 state에 들어있는 값이 input에 표시됩니다.
또한 입력값이 변경되었을 때 호출되는 onChange에는 onChange={handleChange}처럼
handleChange 함수가 호출되도록 했는데 handleChange 함수에서는 setValue( ) 함수를 사용하여 새롭게 변경된 값을 value라는 이름의 state에 저장합니다.
이처럼 제어 컴포넌트를 사용하면 입력값이 리액트 컴포넌트의 state를 통해 관리됩니다.
즉, 여럭 개의 입력 양식 값을 원하는 대로 조종할 수 있다는 말입니다.
입력 양식의 초깃값을 내가 원하는 대로 넣어줄 수 있으며, 다른 양식의 값이 변경되었을 때 또 다른 양식의 값도 자동으로 변경시킬 수 있다는 것입니다.
예를 들어 사용자가 입력한 모든 알파벳을 대문자로 변경시켜서 관리하고 싶다면 아래 코드같이 하면 됩니다.
cosnt handleChange = (event) => {
setValue(event.target.value.toUpperCase());
}