React에 의해서 값이 제어되는 컴포넌트를 제어 컴포넌트, React에 의해서 값이 제어되지 않는 컴포넌트를 비제어 컴포넌트라고 정의할 수 있다.
우리는 보통
, 등의 입력 요소의 태그를 다룰 때 , 요소에 입력되는 값을 state로 관리하거나 DOM API를 통해서 관리할 수 있다.state로 DOM 요소에 입력되는 값을 다루는 컴포넌트가 제어 컴포넌트, DOM API를 통해서 DOM 요소에 입력되는 값을 다루는 컴포넌트가 비제어 컴포넌트 이다.
우리는 React State를 **신뢰 가능한 단일 출처(Single Source of Truth)**로 만들어 두 요소를 결합할 수 있다.
그러면 폼을 렌더링 하는 React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어한다.
이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 제어 컴포넌트 라고 한다.
function MyApp() {
const [name, setName] = useState(null);
const changeName = (e) => {
setName(e.current.value);
}
return (
<input onChange={changeName} value={name}/>
)
}
위의 코드는 input값이 바뀔 때 마다 changeName 함수를 통해 state의 값을 업데이트해주는 제어 컴포넌트 이다.
보다시피 제어 컴포넌트는 사용자 입력을 기반으로 state를 관리하고 update한다.
이러한 방식으로 React에 의해 값이 제어되는 입력, 폼 요소에서 사용된다.
<input value={state}/>
일 때, React의 state에 의해 결정되는데 이를 single source of truth 라고 한다.
즉, 입력한 데이터 상태와 저장된 데이터 상태가 같은 것을 말하고 사용자가 입력한 값과 저장되는 값이 실시간으로 동기화되는 것을 말한다.
제어 컴포넌트는 입력할 때 마다 렌더링을 하기 때문에, 불필요하게 리렌더링되거나 API를 호출할 수 있다. 이러한 문제점을 해결하는 방법으로는 쓰로틀링과 디바운싱이 있다.
대부분 경우 폼을 구현함에 있어 제어 컴포넌트를 사용하는 것이 좋다.
제어 컴포넌트에서 폼 데이터는 React 컴포넌트에서 다루어진다.
대안인 비제어 컴포넌트는 DOM 자체에서 폼 데이터가 다루어진다.
import React, { useRef } from 'React';
function MyApp() {
const nameRef = useRef(null);
return (
<input ref={nameRef}/>
)
}
export default MyApp();
위의 코드는 input의 값은 ref를 통해 접근할 수 있고, 필요한 시점에 이벤트 핸들러를 통해 ref에 저장된 요소의 값을 가져와 활용하는 비제어 컴포넌트이다.
제어 컴포넌트와는 다르게 비제어 컴포넌트는 state로 값을 관리하지 않기 때문에 값이 바뀔 때 마다 리렌더링, API를 호출하지 않아 성능상의 이점이 확실히 있다.
만약 submit 같은 버튼이 있다면 submit을 클릭할 때 실행되는 함수 내에서 ref를 통해 form 내 value들에 접근한다.