Ref
일반적으로는 컴포넌트는 부모 컴포넌트가 자식과 상호작용을 할수 있는것은 props가 유일한 수단입니다. 하지만 자식을 수정하려면 새로운 props 전달을 해야하기 때문에 이러한 흐름에서 벗어나 직접적으로 자식을 수정해야하는일이 가끔씩 있을수가 있습니다. 그럴 때 Ref 프로퍼티를 사용으로 해결이 가능합니다
Ref를 사용해야 할때는 아래와 같이 가이드를 하고 있습니다.
-
포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때.
-
애니메이션을 직접적으로 실행시킬 때.
-
서드 파티 DOM 라이브러리를 React와 같이 사용할 때.
만약에 선언적으로 해결이 가능할 경우에는 ref 사용을 안하시는것이 좋습니다.
Ref는 다음과 같이 React.createRef()을 통해 생성할수 있습니다. 그리고 보통은 컴포넌트가 인스턴스가 생성이 될때 생성을 합니다.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
Ref를 접근하기 위해서는 this.myRef.current를 통해서 접근이 가능합니다.
사용예제 :)
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// textInput DOM 엘리먼트를 저장하기 위한 ref를 생성합니다.
this.textInput = React.createRef();
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
// DOM API를 사용하여 명시적으로 text 타입의 input 엘리먼트를 포커스합니다.
// 주의: 우리는 지금 DOM 노드를 얻기 위해 "current" 프로퍼티에 접근하고 있습니다.
this.textInput.current.focus();
}
render() {
// React에게 우리가 text 타입의 input 엘리먼트를
// 우리가 생성자에서 생성한 `textInput` ref와 연결하고 싶다고 이야기합니다.
return (
<div>
<input
type="text"
ref={this.textInput} />
<input
type="button"
value="Focus the text input"
onClick={this.focusTextInput}
/>
</div>
);
}
}
주의사항
1. 컴포넌트가 마운드가 될때 current 프로퍼티에 DOM 엘리먼트를 대입하고 컴포넌트가 소멸될 때 current 프로퍼티를 다시 null로 넣습니다. 따라서 componentDidMount 또는 componentDidUpdate 생명주기 메서드 전에 작업을 진행해야합니다.
2. 함수형 컴포넌트형 경우에는 인스턴스가 없기 때문에 ref 프로퍼티를 사용할 수 없습니다.
ex) <MyFunctionComponent ref={this.ref} />
다만 DOM 엘리먼트나 클래스 컴포넌트 인스턴스에 접근하는 것은 ref 프로퍼티에 함수 컴포넌트에서 사용하는것은 가능합니다.
ex) const textInput = useRef(null);
콜백 Ref
React에서 ref 설정되고 해제되는 상황을 조금더 세세하게 다루기 위해서 콜백 ref 방법을 제공합니다.
콜백 ref는 React.createRef()를 통해 생성된 ref를 전달하는 대신 함수를 전달합니다. 따라서 아래와 같이 사용이 가능합니다.
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.textInput = null;
this.setTextInputRef = element => {
this.textInput = element;
};
this.focusTextInput = () => {
// DOM API를 사용하여 text 타입의 input 엘리먼트를 포커스합니다.
if (this.textInput) this.textInput.focus();
};
}
componentDidMount() {
// 마운트 되었을 때 자동으로 text 타입의 input 엘리먼트를 포커스합니다.
this.focusTextInput();
}
render() {
// text 타입의 input 엘리먼트의 참조를 인스턴스의 프로퍼티
// (예를 들어`this.textInput`)에 저장하기 위해 `ref` 콜백을 사용합니다.
return (
<div>
<input
type="text"
ref={this.setTextInputRef}
/>
<input
type="button"
value="Focus the text input"
onClick={this.focusTextInput}
/>
</div>
);
}
}