[제어 컴포넌트와 비제어 컴포넌트란?]
React에 의해서 값이 제어되는 컴포넌트를 제어 컴포넌트, React에 의해서 값이 제어되지 않는 컴포넌트를 비제어 컴포넌트라고 합니다. 우리는 보통 <form>, <input> 등의 입력 요소의 태그를 다룰 때, 요소에 입력되는 값을 state로 관리하거나 DOM API를 통해서 관리할 수 있습니다. 어렵게 말하자면, state로 DOM 요소의 값을 다루는 컴포넌트가 제어 컴포넌트, 후자가 비제어 컴포넌트입니다. 이렇게만 말하면 무슨 말인지 모를 수 있지만 간단한 코드랑 같이 확인한다면 이해하는데 훨씬 더 쉬울 것입니다. 바로 코드로 살펴보도록 하겠습니다.
[제어 컴포넌트]
아래의 코드는 <Input/>의 값이 바뀔 때 마다 changeName을 통해 state의 값을 업데이트해주는 제어 컴포넌트입니다.
function MyApp() {
const [name, setName] = useState(null);
const changeName = (e) => {
setName(e.current.value);
}
return (
<input onChange={changeName} value={name}/>
)
}
보시다시피 제어 컴포넌트는 사용자의 입력을 기반으로 state를 관리하고 update합니다. 이러한 방식으로 React에 의해 값이 제어되는 입력, 폼 요소에서 사용됩니다. <input value={state} /> 일 때, React의 state에 의해 결정되는데 이를 "single source of truth"라고 합니다. 즉, 입력한 데이터 상태와 저장된 데이터 상태가 같은 것을 말하고 사용자가 입력한 값과 저장되는 값이 실시간으로 동기화되는 것을 말합니다.
#문제점
제어 컴포넌트는 아무래도 입력할 때마다 렌더링을 하기 때문에, 불필요하게 리렌더링되거나 API를 호출할 수 있습니다. 이러한 문제점을 해결하는 방법으로는 쓰로틀링(Throttling)과 디바운싱(Debouncing)이 있습니다.
- 쓰로틀링(Throttling): 마지막 함수가 호출된 후 일정시간이 지나기 전에 다시 호출되지 않도록 하는 것
- 디바운싱(Debouncing): 연이어 호출되는 함수들 중 마지막(혹은 맨 처음) 함수만 호출하도록 하는 것
#언제 사용?
- 유효성 검사
- 실시간으로 필드 검사를 해야하는 경우
- 조건에 따라 버튼의 활성화 여부가 바뀌는 경우
[비제어 컴포넌트]
아래의 코드는 input의 값은 ref를 통해 접근할 수 있고, 필요한 시점에 이벤트 핸들러를 통해 ref에 저장된 요소의 값을 가져와 활용하는 비제어 컴포넌트입니다.
import React, { useRef } from 'React';
function MyApp() {
const nameRef = useRef(null);
return (
<input ref={nameRef}/>
)
}
export default MyApp();
제어 컴포넌트와는 다르게 비제어 컴포넌트는 state로 값을 관리하지 않기 때문에 값이 바뀔 때마다 리렌더링, API를 호출하지 않기 때문에 성능상의 이점이 확실히 있습니다. 만약 submit 같은 버튼이 있다면 submit을 클릭할 때 실행되는 함수 내에서 ref를 통해 form 내 value들에 접근합니다.
#언제 사용?
제어 컴포넌트와 비제어 컴포넌트들을 언제 사용할 지는 아래 표를 보고 상황에 맞게 사용하시면 됩니다. 일반적으로 모든 form, input 등의 요소에서 상태의 동기화가 필요한 것이 아니고, form 요소가 많다면 모든 컴포넌트에 쓰로틀링이나 디바운싱을 걸어주기는 어렵습니다. 따라서, 이런 경우엔 비제어 컴포넌트를 사용하시는 게 성능상 도움이 됩니다.
#제어 컴포넌트와 비제어 컴포넌트의 차이점
- 가장 큰 차이점은 동기화 (제어 컴포넌트는 항상 동기화)
- 폼 개발 시에는 제어 컴포넌트를 사용 권장
- 제어 컴포넌트에서 폼 데이터는 React 컴포넌트에서 다루어짐
- 비제어 컴포넌트는 DOM 자체에서 폼 데이터가 다루어짐
References
https://goshacmd.com/controlled-vs-uncontrolled-inputs-react/
'1. 웹개발 > 1_1_5 React JS' 카테고리의 다른 글
[React] 리액트를 선택하는 이유 (0) | 2022.09.07 |
---|---|
[React] 클라이언트 사이드 렌더링(CSR)과 서버 사이드 렌더링(SSR) (0) | 2022.08.24 |
[React] 로컬에 있는 json으로 url을 설정하는 방법 (0) | 2022.05.15 |
[React] useMemo 사용법 및 예제 (0) | 2022.04.06 |
[React] useContext 사용법 및 예제 (0) | 2022.04.04 |