React.createRef()
API 대신 callback ref
를 대신 사용하기React.createRef()
를 사용하여 생성하고, ref
attrubute를 통해 React element에 부착됨class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
render
메서드 안에서 ref가 element에 전달되었을 때, 그 노드를 향한 참조는 ref의 current
attribute에 담김const node = this.myRef.current;
ref
attribute가 HTML element에 사용되었을 떄, constructor에서 React.createRef()
로 생성된 ref
는 자신을 전달 받은 DOM element를 current
property값으로 받음ref
attribute가 커스텀 클래스 컴포넌트에 사용되었을 때, ref
객체는 마운트된 컴포넌트의 인스턴스를 current
property값으로 받음ref
attribute를 사용할 수 없음class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// textInput DOM Element를 저장하기 위한 ref 생성
this.textInput = React.createRef();
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
// DOM 노드를 얻기 위해 'current' property에 접근함
this.textInput.current.focus();
}
render() {
return (
{/* constructor에서 생성한 'textInput'과 <input> ref를 연결함 */}
<input
type="text"
ref={this.textInput} />
<input
type="button"
ref={this.focusTextInput} />
)
}
}
current
property에 DOM Element를 할당함current
프로퍼티는 다시 null
이 됨componentDidMount
(첫 렌더링 완료 이후 실행) 또는 componentDidUpdate
(리렌더링 완료 이후 실행) 생명주기 메서드가 호출되기 전 ref
가 업데이트됨class AutoFocusTextInput extends React.Component {
constructor(props) {
super(props);
this.textInput = React.createRef();
}
componentDidMount() {
this.textInput.current.focusTextInput();
}
render() {
return (
<CustomTextInput ref={this.textInput} />
)
}
}
function MyFunctionComponent() {
return <input />;
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.textInput = React.createRef();
}
render() {
// 이 코드는 동작하지 않음
return (
<MyFunctionComponent ref={this.textInput} />
)
}
}
부모 컴포넌트에서 자식 컴포넌트의 DOM 노드에 접근하기를 원할 수 있음
자식 컴포넌트에 ref를 추가하는 것은 좋은 방법이 아님
React 16.3 이상 버젼을 사용하는 경우, ref forwarding
을 사용하는 것이 좋음
Ref forwarding
은 컴포넌트가 자식 컴포넌트의 ref를 자신의 ref로서 외부에 노출시킴React 16.2나 더 낮은 버젼을 사용하는 경우, ref를 명시적으로 다른 이름의 prop으로 전달하여 사용할 수 있음
자식 컴포넌트 수행의 권한이 없다면, 마지막 방법은 findeDOMNode()
를 사용하는 것이나 권장하지 않으며 StrictMode
에서 이 메서드는 없어졌음
ref
callback을 사용하여 인스턴스의 property에 DOM 노드의 참조를 저장할 수 있음function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} />
</div>
);
}
class Parent extends React.Component {
render() {
return (
<CustomTextInput
inputRef={el => this.inputElement = el} />
)
}
}
ref
attribute에 ref callback을 전달함ref
callback이 인라인 함수로 정의되어 있으면, ref
callback은 업데이트 과정 중 처음에는 null
로 다음에는 DOM Element로 총 두 번 호출됨ref
callback의 새로운 인스턴스가 생성됨ref
callback을 클래스에 바인딩된 메서드로 정의함으로서 이러한 현상에서 벗어날 수 있음const refContainer = useRef(initialValue);
useRef
current
property를 가진 변경 가능한 ref 객체를 반환함uesRef
는 자식 컴포넌트에 직접적으로 접근할 때 주로 사용됨function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focust();
}
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
React에 ref 객체를 전달하면, React는 노드가 바뀔 때 마다 ref의 current propery로 대응되는 DOM 노드를 설정함
useRef()는 JavaScirpt 객체를 생성하기 때문에 변하는 값을 저장할 수 있음
callback ref
를 대신 사용하기const SimpleCallbackRef = () => {
let inputRef: HTMLInputElement | null;
const onClick = () => {
console.log('INPUT VALUE: ', inputRef?.value);
}
const onFocusClick = () => {
console.log('Focus input');
inputRef?.focus();
}
console.log('Rendering')
return (
<div>
<input ref={node => { inputRef = node; }} />
<button onClick={onClick}>Log value</button>
<button onClick={onFocusClick}>Focus on input</button>
</div>
);
};
React.forwardRef
는 전달받은 ref
attribute를 하위 트리의 다른 컴포넌트에 전달하는 React 컴포넌트를 생성함React.forwardRef
사용 예import React from 'react';
type ForwardedInputProps = {
placeholder?: string
};
const ForwardedInput = React.forwardRef<HTMLInputElement, ForwardedInputProps>(({ placeholder }, ref) => (
<input ref={ref} placeholder={placeholder} />
));
const SimpleForwardRef = () => {
const inputRef = React.useRef<HTMLInputElement>(null);
const selectText = () => {
inputRef.current?.select();
}
return (
<div>
<ForwardedInput ref={inputRef} placeholder="Type here"/>
<button onClick={selectText}>Select text</button>
</div>
);
};
React.forwardRef
를 사용해서 전달 받은 ref
를 DOM input에 내려줌State | Ref | |
---|---|---|
공통점 | 컴포넌트 라이프 사이클 내 유지됨, 값 변경 가능 | 컴포넌트 라이프 사이클 내 유지됨, 값 변경 가능 |
차이점 | 값 변경시 리렌더링됨 | 값 변경시 리렌더링 안 됨 |
createRef | useRef | |
---|---|---|
공통점 | ref를 생성함 | ref를 생성함 |
차이점 | 리렌더링시 새 ref를 생성함 | 리렌더링시 같은 ref를 사용함 |