대표적인 폼 태그 엘리먼트로는 <input/>
, <textarea/>
, <select/>
가 있다.
이들은 사용자 입력을 기반으로 자신의 state를 관리하고 업데이트하며, 각각의 value Attribute를 통해 값에 접근할 수 있다.
즉, 사용자가 입력한 값은 value Attribute에 저장되고, 이 속성은 DOM에 있으므로 결과적으로 사용자 입력값은 DOM에 저장된다고 볼 수 있다.
하나의 상태는 한 곳에만 있어야 한다.
input 태그는 사용자 입력값에 대해 value Attribute가 실시간으로 갱신된다.
value 속성은 최신값을 가지고 있어 신뢰할 수 있으며, 단 하나이기 때문에 유일하다.
따라서 value Attribute는 신뢰 가능한 단일 출처이다.
const form = document.querySelector('form');
let inputValue = '';
let textareaValue = '';
let selectValue = '';
const onSubmit = (e) => {
e.preventDefault();
inputValue = e.target.elements['input-elem'].value;
textareaValue = e.target.elements['textarea-elem'].value;
selectValue = e.target.elements['select-elem'].value;
};
form.addEventListener('submit', onSubmit);
위 코드는 사용자의 입력값이라는 상태를 value Attribute와 let 변수라는 두 가지의 출처로 나누어 가진다.
![]() | ![]() |
---|
만약 오른쪽 그림과 같이 어떤 이유로 value 속성과 변수 간의 연관관계가 깨진다면, let 변수의 값은 더 이상 갱신되지 않아 데이터 불일치가 발생할 수 있다.
그래서 신뢰 가능한 단일 출처를 가지는 것이 중요하다.
리액트는 제어 컴포넌트를 퉁해 이러한 문제를 해결할 수 있다.
React 상태(state)를 통해 입력값을 제어하는 컴포넌트
import { useState } from 'react';
export default function App() {
const [name, setName] = setState('');
return (
<form>
<label>name : </label>
<input
value={name}
onChange={(e) => {
setName(e.target.value);
}}
placeholder="이름을 입력하세요."
/>
</form>
)
}
제어 컴포넌트는 value 속성과 state를 결합해 name state를 신뢰 가능한 단일 출처로 만든다.
즉, Form의 사용자 입력값을 React가 직접 제어한다.
React의 상태가 아닌, DOM 자체가 입력값을 제어하는 방식
import { useRef } from 'react';
export default function App() {
const nameRef = useRef(null);
const submitName = (e) => {
e.preventDefault();
console.log(nameRef.current.value);
};
return (
<form onSubmit={submitName}>
<label>name : </label>
<input ref={nameRef} placeholder="이름을 입력하세요." />
</form>
)
}
비제어 컴포넌트는 ref를 사용하여 input 태그에 접근한다. ref는 순수 자바스크립트 객체이며, current 프로퍼티를 통해 input 태그에 접근할 수 있다.
ref는 직접 변화가 되어도 리렌더링이 발생하지 않는 특성이 있다.
비제어 컴포넌트에서는 React가 크게 관여하지 않으며, HTML Form Elements와 유사하게 동작한다.
따라서 value Attribute가 신뢰 가능한 단일 출처가 된다.
제어 컴포넌트 | 비제어 컴포넌트 | |
---|---|---|
데이터 관리 주체 | React | DOM |
데이터 갱신 시점 | 사용자가 값을 입력할 때마다 갱신 | 특정 시점에서 DOM에서 pull하여 갱신 |
리렌더링 여부 | 값을 입력할 때마다 발생 | 값을 입력할 때는 발생하지 않음 |
제어 컴포넌트 | 비제어 컴포넌트 | |
---|---|---|
Submit과 같은 일회성 정보 검색 | O | O |
Submit 시 유효성 검사 | O | O |
조건에 따른 Submit 버튼 (비)활성화 | O | X |
즉각적인 필드 유효성 검사 | O | X |
특정 입력 형식 적용 | O | X |
동적 입력 | O | X |