Controlled Component
)React에 의해 값이 제어되는 입력 폼 엘리먼트
HTML에서 <input>
, <textarea>
, <select>
와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state
를 관리하고 업데이트한다.
React에서는 변경할 수 있는 state
가 일반적으로 컴포넌트의 state
속성에 유지되며 setState()
함수에 의해 업데이트 된다.
그러면 폼을 렌더링하는 React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어한다.
이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 "제어 컴포넌트 (controlled component)" 라고 한다.
const Form = () => {
const [input, setInput] = useState('');
const onChange = (e) => setInput(e.target.value);
return (
<div>
<input onChange={onChange} />
</div>
)
}
위 예시처럼, 사용자의 입력을 받는 태그에 event 객체를 이용해 setState()
로 값을 저장하는 방식과 같이, React에 의해 값을 제어되는 컴포넌트를 제어 컴포넌트이다.
제어 컴포넌트는 사용자가 입력한 값과 저장되는 값이 실시간으로 동기화된다.
사용자가 입력할 때마다 보여지는 값이 업데이트 되고, 이 입력값은 항상 React State에 의해 결정된다.
다른 UI 엘리먼트에 입력값을 전달하거나 다른 이벤트 핸들러에서 값을 재설정할 수 있다.
Unctrolled Component
)
setState()
가 아닌ref
를 사용하여 DOM에서 폼 값을 가져오는 컴포넌트
비제어 컴포넌트는 DOM 자체에서 폼 데이터가 다루어진다.
모든 state 업데이트에 대한 이벤트 핸들러를 작성하는 제어 컴포넌트와 달리,
비제어 컴포넌트는 ref
를 사용하여 DOM에서 폼 값을 가져올 수 있다.
const NameForm = () => {
const inputRef = useRef();
const handleSubmit = () => console.log(inputRef.current.value);
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type='text' ref={inputRef} />
</label>
</form>
)
}
따라서 제어 컴포넌트의 경우 사용자가 입력을 하는 액션을 취할때마다 리렌더링을 발생시키는 반면,
비제어 컴포넌트는 ref
를 사용하기 때문에 사용자가 직접 트리거 하기 전까지는 리렌더링을 발생시키지도 않고 값을 동기화 시키지도 않는다.
값을 항상 최신값으로 유지한다. (setState()
를 이용해서) 새로운 값을 입력할 때마다 새롭게 값을 업데이트해준다.
데이터와 UI에서 입력한 값이 항상 동기화된다.
필드에서 값을 트리거 해야 값을 얻을 수 있다. (ex. '전송' 버튼을 눌러 폼 제출)
'전송' 버튼을 누르는 등 트리거 하기 전까지는 값이 변경되지 않는다.
기능 | 제어 컴포넌트 | 비제어 컴포넌트 |
---|---|---|
일회성 정보 검색 ( 예: 제출 ) | O | O |
제출 시 값 검증 | O | O |
실시간으로 필드값의 유효성 검사 | O | X |
조건부로 제출 버튼 비활성화 ( disabled ) | O | X |
실시간으로 입력 형식 적용하기 ( 숫자만 가능하게 등 ) | O | X |
동적 입력 | O | X |
⭐ 정리!
- 즉각적으로, 실시간으로 값에 대한 피드백이 필요하다 >
제어 컴포넌트
사용- 즉각적인 피드백이 불필요하고 제출시에만 값이 필요하다, 불필요한 렌더링과 값 동기화가 싫다 >
비제어 컴포넌트
사용
유효성 검사 필요할 때
유효한 데이터 없는 경우 전송 버튼의 상태를 disabled
해야 할 때
신용 카드 같은 특정 입력 방식 적용할 때
제어 컴포넌트는 UI에서 입력된 데이터 상태와 React의 state 데이터 상태가 항상 일치하는 것이기 때문에,
사용자가 입력할 때마다 데이터 동기화를 위해 불필요한 리렌더링이 발생하고, 불필요한 값까지 업데이트 된다.
ㅇ
아
안
안ㄴ
안녀
안녕
안녕!
이러한 불필요한 리렌더링, 값 업데이트를 막기 위해서는 throttle & debounce를 사용할 수 있다.
throttle
: 마지막 함수 호출 후 일정 시간이 지나기 전에 해당 함수가 다시 호출되지 않도록 설정해주는 것debounce
: 연이어 호출되는 함수 중 마지막 또는 제일 첫 함수만 호출되도록 설정해주는 것
만약 form 컴포넌트에서 값이 트리거된 이후에만 값이 업데이트 되어도 문제가 없다면,
ref
를 사용하는 비제어 컴포넌트를 사용하는 게 불필요한 리렌더링 방지하는 데 도움이 될 수 있다.
이러한 비제어 컴포넌트를 사용해 렌더링을 최적화하는 라이브러리가 React-Hook-Form
이다.