오늘은 Ref의 다양한 활용법에 대해 알아보겠습니다. forwardRef는 특수한 컴포넌트이고, Callback Ref는 useRef 대신 특수한 경우에 사용하는 기법입니다.
forwardRef
forwardRef는 부모 컴포넌트에서 자식 컴포넌트의 ref를 다루고 싶을 때 사용합니다. 리액트에서는 자식 컴포넌트의 값을 부모로 올리는 것이 어려우므로 ref를 부모 컴포넌트에서 만들어서 자식에게 내려보내주어야 합니다. (state를 생각해보세요)
import { useEffect, useRef } from 'react';
const Parent = () => {
const ref = useRef();
useEffect(() => {
// 여기서 ref 조작
}, []);
return <Children ref={ref} />;
}
이제 Children을 구현해야 하는데 다음과 같이 하면 안 되나 생각할 수 있습니다. 그런데 해보면 안 됩니다.. ㅎㅎ. ref는 props로 전달할 수 없기 때문입니다.
const Children = ({ ref }) => {
return <div ref={ref}>자식</div>;
};
꼼수로는 ref 대신 다른 props 이름으로 전달하는 방법이 있습니다. innerRef 같은 것을 사용해서요.
const Parent = () => {
const ref = useRef();
useEffect(() => {
// 여기서 ref 조작
}, []);
return <Children innerRef={ref} />;
}
const Children = ({ innerRef }) => {
return <div ref={innerRef}>자식</div>;
};
공식적인 방법은 forwardRef를 사용하는 것입니다.
import { forwardRef } from 'react';
const Children = forwardRef(({}, ref) => {
return <div ref={ref}>자식</div>;
});
forwardRef를 사용하면 props 매개변수 다음에 ref 매개변수가 추가됩니다. 이를 자식의 ref에 전달하면 됩니다.
class 컴포넌트에서는 다음과 같이 ref를 전달합니다. forwardRef를 쓰는 대신, class 내부에서도 createRef로 한 번 더 만들어주는 게 핵심입니다.
import { useEffect, useRef, createRef, Component } from 'react';
const Parent = () => {
const ref = useRef();
useEffect(() => {
// 여기서 ref 조작
console.log(ref.current.innerRef);
}, []);
return <Children ref={ref} />;
}
class Children extends Component {
innerRef = React.createRef();
render() {
return <div ref={this.innerRef}>자식</div>;
}
}
https://ko.reactjs.org/docs/forwarding-refs.html
Callback Ref
콜백 ref는 ref가 설정되고 해제되는 상황을 좀 더 세세하게 다루기 위한 방법입니다.
ref 자리에 createRef나 useRef를 넣는 대신 함수를 전달하면 됩니다.
class CallbackRefExample extends Component {
inputRef;
render() {
return (
<input ref={(c) => { this.inputRef = c; }} />
);
}
}
좀 더 나은 방식은 메서드로 분리하는 겁니다.
class CallbackRefExample extends Component {
inputRef;
setRef = (c) => {
this.inputRef = c;
}
render() {
return (
<input ref={this.setRef} />
);
}
}
inputRef를 통해서 input 태그에 접근할 수 있게 되는데, setRef가 함수이므로 여기서 추가적인 작업을 할 수 있게 됩니다. 특수한 경우에 사용할 수 있습니다.
https://ko.reactjs.org/docs/refs-and-the-dom.html#callback-refs
다음 시간에는 ErrorBoundary에 대해 알아보겠습니다!