개발/기타

useRef는 언제 사용하나요?

JonghwanWon 2024. 9. 28. 10:22

useRef는 언제 사용하나요?

DOM 조작 및 접근: 특정 DOM 요소에 접근하거나 조작할 때 사용

값의 변경 추적: 값이 변경되더라도 리렌더링되지 않는다는 특징을 활용, 값이 유지할 때 사용

const ref = React.useRef(null);
<div ref={ref}>{children}</div>;

 

useRef를 통해 렌더링 이후 해당 DOM 노드를 참조하고, 컴포넌트가 언마운트될 때 다시 null로 설정됩니다.


렌더링 이후 특정 DOM 요소에 접근하기: useEffect와 callback ref

useEffect를 사용한 경우

useEffect를 통해 렌더링 이후 특정 DOM 요소에 접근할 수 있습니다.

const ref = React.useRef(null);

React.useEffect(() => {
  if (ref.current) {
    ref.current.focus();
  }
}, []);

<input ref={ref} />;

 

이 방법은 초기 렌더링 이후 특정 작업을 수행하는 데 유용합니다. 그러나 렌더링 타이밍이나 조건부 렌더링이 있는 경우 useEffect의 실행 시점과 ref의 상태가 맞지 않을 수 있습니다.

복잡한 상황에서의 문제점: 조건부 렌더링

렌더링이 지연되거나 특정 조건에 따라 DOM 요소가 생성될 때, useEffectuseRef 조합은 예상치 못한 동작을 할 수 있습니다.

function App() {
  const ref = React.useRef(null);

  React.useEffect(() => {
    // 🚨 이 시점에 ref.current는 항상 null입니다.
    ref.current?.focus();
  }, []);

  return <Form ref={ref} />;
}

const Form = React.forwardRef((props, ref) => {
  const [show, setShow] = React.useState(false);

  return (
    <div>
      <button type="button" onClick={() => setShow(true)}>
        Show
      </button>
      {/* 조건부 렌더링: 이때 ref는 비어있습니다. */}
      {show && <input ref={ref} />}
    </div>
  );
});

 

위와 같은 상황에서는 useEffect가 실행되는 시점에 ref가 아직 설정되지 않아 원하는 동작을 보장할 수 없습니다.


callback ref: useEffect 없이 DOM 요소에 안전하게 접근하기

callback refuseEffect 없이 DOM 요소에 직접적으로 접근할 수 있는 방법입니다. 이 방식은 DOM 노드가 렌더링되었을 때 호출되며, DOM의 생명주기에 바인딩됩니다.

const ref = React.useCallback((node) => {
  if (node) {
    node.focus();
  }
}, []);

return <input ref={ref} />;

 

callback refuseRef의 대체 방법으로, DOM이 렌더링될 때마다 실행되기 때문에 useEffect의 실행 타이밍 문제를 해결할 수 있습니다.

useCallback을 사용하여 함수 참조를 유지함으로써 불필요한 렌더링을 방지할 수 있습니다.

Ref Props의 다형성

React의 ref는 객체뿐만 아니라 함수도 전달할 수 있습니다. 이는 React의 ref 시스템이 매우 유연함을 보여줍니다.

type Ref<T> = RefCallback<T> | RefObject<T> | null;

 

useRef는 단순히 syntactic sugar에 불과합니다.


언제 callback ref를 고려해야 할까?

렌더링 이후 DOM 노드와 상호작용해야 할 때 성급하게 useRef + useEffect를 사용하는 대신 callback ref를 사용하여 불필요한 문제를 예방할 수 있습니다.

특히 조건부 렌더링이나 렌더링 타이밍 이슈가 있을 때 callback ref는 효과적인 대안이 될 수 있습니다.

 

참고 자료

과거의 리액트 문서

tkdodo’s blog - Avoiding useEffect with callback refs

tanstack/virtual의 measureElement

최신 리액트 문서