엘리먼트 중에는 상태를 가지고 있는 것들이 있습니다.
등이 이 예에 속합니다. 그래서 엘리먼트의 '상태'를 누가 관리하느냐에 따라 Contorlled
와 Uncontrolled Component
로 나뉩니다.
엘리먼트를 가지고 있는 컴포넌트가 관리한다면, Contorlled Component
, 엘리먼트의 상태를 관리하지 않고 엘리먼트의 참조만 컴포넌트가 소유한다면, Uncontorlled Component
라고 할 수 있습니다.
이에 대한 자세한 사항은 리액트 공식문서를 확인해보시면 되니 참고 부탁드리겠습니다.
우리는 React state
를 “신뢰 가능한 단일 출처 (single source of truth)“로 만들어 두 요소를 결합할 수 있습니다.
그러면 폼을 렌더링하는 React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어합니다. 이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 제어 컴포넌트 (controlled component)
라고 합니다.
input 엘리먼트로 아래와 같이 예를 들어보도록 하겠습니다.
import React, { Component } from "react";
export class ControlledComponent extends Component {
constructor() {
super();
this.state = {
value: "",
};
}
render() {
const { value } = this.state;
return (
<div>
<input value={value} onChange={this.change} />
<button onClick={this.click}>전송</button>
</div>
);
}
change = (e) => {
console.log(e.target.value);
// render가 다시 일어남
this.setState({ value: e.target.value });
};
click = () => {
console.log(this.state.value);
};
}
export default ControlledComponent;
대부분 경우에 폼을 구현하는데 제어 컴포넌트
를 사용하는 것이 좋습니다. 제어 컴포넌트
에서 폼 데이터는 React 컴포넌트에서 다루어집니다. 대안인 비제어 컴포넌트
는 DOM 자체
에서 폼 데이터가 다루어집니다.
모든 state 업데이트에 대한 이벤트 핸들러를 작성하는 대신 비제어 컴포넌트
를 만들려면 ref
를 사용하여 DOM에서 폼 값을 가져올 수 있습니다.
import React, { Component } from "react";
export class UncontrolledComponent extends Component {
inputRef = React.createRef();
render() {
console.log("initial render", this.inputRef);
return (
<div>
<input ref={this.inputRef} />
<button onClick={this.click}>전송</button>
</div>
);
}
componentDidMount() {
console.log("componentDidMount", this.inputRef);
}
click = () => {
// input 엘리먼트의 현재 상태 값(value)을 꺼내서 전송한다.
// const input = document.querySelector("#my-input");
// console.log(input.value);
// 위의 코드는 실제 DOM을 업데이트하므로 지양해야하는 방법!
console.log(this.inputRef.current.value);
};
}
export default UncontrolledComponent;
예를 들어, 로그인 유효성 검사 로직이 매번 state
값이 변화함에 따라 화면에 그려내야하는 경우라면 제어 컴포넌트
가 쉬운 방식일 것입니다.
그리고 예를 들어 마우스로 비제어 컴포넌트
에 올렸을 때, focus 되게 하고 싶다면, 이벤트에 맞춰서 실제 엘리먼트에 focus를 주어야하므로 ref로 실제 DOM을 참조하여 액션을 취하는 것이 더 좋은 방법
이 될 것입니다.
이렇게 각자의 경우에 필요한 때에 적절한 방법을 취하는 것이 좋습니다. 저도 이렇게 각 상황에 따라 맞는 React 문법을 사용할 수 있도록 해야할 것 같습니다💪