제어 컴포넌트 vs 비제어 컴포넌트
https://goshacmd.com/controlled-vs-uncontrolled-inputs-react/ 번역
비제어
| 제어 되지 않은 input은 기존 HTML 양식 입력과 같습니다.
비제어 input은 입력한 내용을 기억합니다. 비제어 입력값은 ref 로 가져올 수 있습니다.
예를 들어 버튼의 onClick 핸들러에서:
즉, 필요할 때 필드에서 값을 '가져와야'합니다. 이는 폼이 제출될 때 발생할 수 있습니다.
위와 같은 방식이 폼 입력을 구현하는 가장 간단한 방법입니다. 실제로 간단한 양식이거나 React를 배울 때 이 방식을 사용하는 것은 분명 유효하지만, 그다지 강력하지는 않으므로 제어된 입력을 살펴봅시다.
제어
| 제어된 input은 현재 값을 prop으로 받아들이고, 그 값을 변경하는 콜백함수(상태 setter)를 받습니다.
좀더 리액트적인 접근 방식이지만 항상 사용한다는 의미는 아닙니다.
하지만 이 input의 value 값은 어딘가의 상태에 저장되어야 합니다.
일반적으로 input을 렌더링하는 컴포넌트(폼 컴포넌트라고 함)가 그것을 상태에 저장합니다.
(물론 다른 컴포넌트의 상태나 Redux같은 별도의 상태 저장소에 있을 수도 있습니다.)
새 문자를 입력할 때마다 handleNameChange 함수가 호출됩니다. 이 함수는 input의 새로운 입력 값을 받아 상태에 저장하는 역할을 합니다.
- 빈 문자열 "" 로 시작합니다.
- 'a'를 입력하면 handleNameChange가 'a'를 가져와 setState를 호출합니다. 그러면 input이 다시 렌더링되어 'a'라는 값을 가집니다.
- 'b'를 입력하면 handleNameChange가 'ab' 값을 가져와 이를 상태로 설정합니다. input이 다시 한 번 레더링되어 이제 input의 값은 'ab'가 됩니다.
이 흐름은 폼 컴포넌트에 값 변경을 'push'하므로, Form 컴포넌트는 명시적으로 요청할 필요없이 항상 input의 현재 값을 가지고 있습니다.
즉, 데이터(상태)와 UI(input)이 항상 동기화됩니다. 상태는 input에 값을 제공하고, input은 Form 컴포넌트에 현재 값을 변경하라고 요청합니다.
다시말해, 폼 컴포넌트는 input의 값 변경에 즉시 응답할 수 있습니다.
예를 들어:
- 유효성 검사 등 인플레이스 피드백
- 폼의 모든 필드가 유효하지 않으면 버튼 비활성화
- 특정 입력 형식 강제 적용(신용카드 번호 등)
이러한 기능이 필요하지 않고 제어되지 않는 것이 더 간편하다고 생각한다면 그렇게 하세요.
"제어"하는 요소
폼의 다른 양식 요소들(checkbox, radio, select ... textarea)도 제어가 필요하다면, 그들의 값을 prop으로 설정하기만 하면 됩니다.
각 폼 요소마다 값을 설정하는 데 사용되는 prop이 다르므로 다음 표를 참고하는 것이 좋습니다.
Element | Value property | Change callback | New value in the callback |
<input type="text" /> |
value="string" | onChange | event.target.value |
<input type="checkbox" /> |
checked={boolean} | onChange | event.target.checked |
<input type="radio" /> |
checked={boolean} | onChange | event.target.checked |
<textarea /> | value="string" | onChange | event.target.value |
<select /> |
value="option value" | onChange | event.target.value |
결론
제어 양식, 비제어 양식은 각 강점이 있습니다. 구체적인 상황을 고려하여 자신에게 적합한 방식을 선택하면 됩니다.
UI 피드백 측면에서 폼이 매우 단순하다면, 비제어 입력도 괜찮습니다.
기능 | uncontrolled | controlled |
일회성 값 검색(예: 폼 제출 시) | ✅ | ✅ |
제출 시 유효성 검사 | ✅ | ✅ |
즉각적인 필드 유효성 검사 | ❌ | ✅ |
조건부로 제출 버튼 비활성화 | ❌ | ✅ |
입력 형식 적용(신용카드 번호 등) | ❌ | ✅ |
하나의 데이터에 대한 여러 입력 | ❌ | ✅ |
동적 입력(dynamic inputs) | ❌ | ✅ |
또한, 한 번 결정하면 끝나는 것이 아니라 언제든 제어 입력으로 마이그레이션할 수 있습니다.
비제어 입력에서 제어 입력으로 전환하는 것은 어렵지 않습니다.