회사에서든 집에서든 개발을 하다 보면 모르는 개념이 많이 생긴다. 실제로 사용하고는 있지만 그 원리를 모르면 모르는 것과 마찬가지이기 때문에 매일 모르는 부분을 하나씩 없애간다는 생각으로 궁금증을 하나씩 해결해나가려고 한다. 오늘이 그 시작이다.
최근 Slate 라이브러리(https://github.com/ianstormtaylor/slate)를 사용하기 위해 예제 코드와 공식 문서를 둘러보던 중 React.forwardRef()
를 사용한 코드들이 많이 있었다.
// slate 예제 코드 (https://github.com/ianstormtaylor/slate/blob/main/site/components.tsx)
export const Icon = React.forwardRef(
(
{ className, ...props }: PropsWithChildren<BaseProps>,
ref: Ref<OrNull<HTMLSpanElement>>
) => (
<span
{...props}
ref={ref}
className={cx(
'material-icons',
className,
css`
font-size: 18px;
vertical-align: text-bottom;
`
)}
/>
)
)
코드 사용을 봤을 때 Ref를 컴포넌트에 전달해주는 용도로 쓰고 있는 것임을 얼추 알 수 있었지만, 이렇게 막연하게 넘어가면 발전이 없기 때문에 자세히 공부해보기로 결정했다.
가장 좋은 레퍼런스인 리액트 공식 문서로 ref 개념을 복습했다. (https://ko.reactjs.org/docs/refs-and-the-dom.html)
forwardRef()
는 블로그를 통해 배웠다. (https://www.daleseo.com/react-forward-ref/)
기존에 Ref를 사용하는 방법으로 React.createRef()
와 useRef hook
방식을 주로 사용했는데, 새로운 Ref를 다루는 방식을 하나 더 배우게된 것 같다.
Ref
는 render 메서드 내부의 DOM 노드나 React 엘리먼트에 접근할 수 있는 방법을 제공한다.
DOM 노드의 HTML 요소를 직접다루기 위해서 사용되기도 하고, 컴포넌트에 ref를달아 컴포넌트 내부의 메서드 및 멤버 변수(주로 다른 컴포넌트 내부의 HTML element 접근 용도)에 접근할 수 있다. 다만 특수한 경우를 제외하고 컴포넌트에 ref를 달아서 다른 컴포넌트로 전달하는 방식은 부모에서 자식으로 흘러가는 React의 데이터 흐름에 위배될 수 있기 때문에 사용하기전에 고민이 필요하다.
React에서는 특수한 목적으로 사용되기 때문에 일반적인 용도로 사용하지 못하는 props이 몇 가지 존재한다. ref
prop은 HTML 엘리먼트 접근이라는 특수한 용도로 사용되므로 일반적인 prop으로 사용할 수 없다.
HTML 엘리먼트가 아닌 React 컴포넌트에서 ref
prop을 사용하려면 React에서 제공하는 forwardRef()
함수를 사용해야 한다. React 컴포넌트를 forwardRef()
함수로 감싸면 두 번째 매개변수로 ref
를 전달받기 때문에, 이를 통해 외부에서 ref
prop을 넘길 수 있다.
import React, { forwardRef, useRef } from react;
const Input = forwardRef((props, ref) => {
return <input ref={ref}/>
});
function Field() {
const inputRef = useRef(null);
function handleFocus() {
inputRef.current.focus();
}
return (
<>
<Input ref={inputRef}/>
<button onClick={handleFocus}>입력란 포커스</button>
<>
)
}
지금까지
Ref
개념을 복습하고forwardRef
를 사용하는 이유와 사용법을 알아보았다. 확실히 함수의 존재 이유와 사용법을 제대로 알게되니 후련하고 더욱 이해도가 높아진 것 같다. 앞으로도 모르는 개념이 있다면 확실하게 알고 넘어가야 겠다.