본문 바로가기

이것저것 스터디📚/React - 공식 문서

React 공식문서 -forwardRef

- forwardRef를 사용하면 컴포넌트가 ref를 사용하여 부모 컴포넌트에 DOM 노드를 노출할 수 있다.

- 즉, 컴포넌트가 ref를 받아 자식 컴포넌트로 전달하도록 하려면 forwardRef를 사용할 수 있다.

- forwardRef는 렌더링 함수를 인자로 받고, React는 props 및 ref와 함께 이 함수를 호출한다.

const MyInput = forwardRef(function MyInput(props, ref) {
  return (
    <label>
      {props.label}
      <input ref={ref} />
    </label>
  );
});

Exposing an imperative handle instead of a DOM node(DOM 노드 대신 명령형 핸들 노출하기)

- React에서 DOM 요소를 직접 노출하는 대신, 더 안전하고 추상화된 방식으로 상호작용 하는 방법으로 "명령형 핸들"이라는 사용자 정의 객체를 사용할 수 있다.

- 이때, useImperativeHandle을 사용할 수 있다.

// App.js
import { useRef } from 'react';
import MyInput from './MyInput.js';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
    // This won't work because the DOM node isn't exposed:
    // DOM 노드가 노출되지 않았기 때문에 작동하지 않습니다:
    // ref.current.style.opacity = 0.5;
  }

  return (
    <form>
      <MyInput label="Enter your name:" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}

// MyInput.js
import { forwardRef, useRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => {
    return {
      focus() {
        inputRef.current.focus();
      },
      scrollIntoView() {
        inputRef.current.scrollIntoView();
      },
    };
  }, []);

  return <input {...props} ref={inputRef} />;
});

- 즉, 위와 같이 "명령형 핸들"을 사용하면, DOM 노드에 대해 노출하는 정보를 최소한으로 제한할 수 있다.


My component is wrapped in forwardRef, but the ref to it is always null(컴포넌트가 forwardRef로 감싸져 있지만, 컴포넌트의 ref는 항상 null 입니다.)

- 컴포넌트가 forwardRef로 감싸져 있지만, ref가 항상 null인 경우에는 컴포넌트 내부에서 ref를 실제로 사용하는 것을 잊어버렸음을 의미한다.

- 즉, 다음 예시와 같은 경우일 수가 있다.

// ref로 아무 작업도 하지 않는 경우
const MyInput = forwardRef(function MyInput({ label }, ref) {
  return (
    <label>
      {label}
      <input />
    </label>
  );
});
// 일부 로직이 조건부인 경우
// 만약 showInput이 false이면 ref가 어떤 노드로도 전달되지 않으며, ref는 null이다.
const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
  return (
    <label>
      {label}
      {showInput && <input ref={ref} />}
    </label>
  );
});

const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
  return (
    <label>
      {label}
      <Panel isExpanded={showInput}>
        <input ref={ref} />
      </Panel>
    </label>
  );
});

* 참고 : React 공식문서(https://react-ko.dev/learn)