✍️ 기록/React

[React forwardRef useImperativeHandle] 자식 컴포넌트 접근

김물사 2025. 3. 11. 17:01

❌ React 19에서는 더 이상 사용하지 않는다고 하고 ref 대신 prop로 전달하는 방법으로 안내하고 있습니다.

 

📌 forwardRef

 - React에서 forwardRef는 부모 컴포넌트에서 자식 컴포넌트의 DOM 요소나 컴포넌트 인스턴스에 직접 접근할 수 있도록 도와주는 기능.

 

🔗 react/forwardRef

 

📍 필요한 이유

- 부모 컴포넌트가 자식 컴포넌트의 내부 DOM 요소에 직접 접근할 수 없지만 ref를 사용하면 DOM 요소에 접근할 수 있고, forwardRef를 활용하면 컴포넌트 간에 전달이 가능합니다!

 

✅ 사용 예

- focus() : 부모 컴포넌트에서 자식 컴포넌트의 input 요소에 포커스 이

- clear()  : 입력 값을 지우는 메서드를 정의하여 부모에서 제어 가능하게 할 때

-scroll   : 특정 요소로 스크롤 이동하도록 할 때

- 기타 등

 

📍 사용 방법

forwardRef를 이용하여 부모 컴포넌트에서 자식 컴포넌트 접근

 

// ✅ TestPage.jsx -> Parent Component
import { useRef } from "react";
import { TistoryInput } from "./TistoryInput";

export const TestPage = () => {
  const inputRef = useRef(null);

  const focusInput = () => {
    console.log(inputRef.current)
    inputRef.current?.focus();
  };

  return( 
    <div className="test-wrap">
      <TistoryInput ref={inputRef} placeholder="티스토리 input" />
      <button 
        type="button"
        onClick={focusInput}
      >
        <span>버튼</span>
      </button>
    </div>
  )
}
// ✅ TistoryInput.jsx -> Child Component
import { forwardRef } from "react"

export const TistoryInput = forwardRef((props, ref) => { // forwardRef 
  return( 
    <input 
      type="text" 
      ref={ref}
      {...props}  
    />
  )
});

 

✅ 버튼 클릭 시 input 에게 focus 이동

👆 console.log(inputRef.current) 확인 결과

📍 useImperativeHandle

useImperativeHandle은 forwarRef와 함께 사용되어 부모 컴포넌트가

자식 컴포넌트의 특정 메서드만 접근할 수 있도록 제한하는 역할을 수행하여

필요한 기능 사용으로 컴포넌트의 재사용성을 높일 수 있습니다 👍 

 

📍 useImperativeHandle 사용 방법

// ✅ TestPage.jsx -> Parent Component
import { useRef } from "react";
import { TistoryInput } from "./TistoryInput";

export const TestPage = () => {
  const inputRef = useRef(null);

  const focusInput = () => {
    console.log(inputRef.current)
    inputRef.current?.focus();
  };
  const inputInit = () => {
    inputRef.current?.init();
  }
  const inputError = () => {
    inputRef.current?.error();
  }
  return( 
    <div className="test-wrap">
      <TistoryInput ref={inputRef} placeholder="티스토리 input" />
      <div className="btns">
        <button 
          type="button"
          onClick={focusInput}
        >
          <span>버튼</span>
        </button>
        <button 
          type="button"
          onClick={inputInit}
        >
          <span>초기화</span>
        </button>
        <button 
          type="button"
          onClick={inputError}
        >
          <span>Error</span>
        </button>
      </div>
    </div>
  )
}
import { forwardRef, useImperativeHandle, useRef, useState } from "react"

export const TistoryInput = forwardRef((props, ref) => {
  const inputRef = useRef(null);
  const [error, setError] = useState(false);
  
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current?.focus()
    },
    init: () => {
      inputRef.current.value = "";
      setError(false);
    },
    error: () => {
      inputRef.current.focus();
      setError(true);
    },
  }));

  return( 
    <div className="input-item">
      <input 
        type="text" 
        ref={inputRef}
        {...props}  
        className={error ? 'error': ''}
      />
      {error && <p className="error-txt">Error</p>}
    </div>
  )
});

 

✅ 부모에서 input 컴포넌트에 접근하여 foucs, init, error  메서드를 호출할 수 있습니다.

 

👆  실행화면

foucs : 포커스

init: value 초기화, error state 변경

error : setState 변경, 포커스 이동

 

✅ 예제를 통해 상위 컴포넌트에서 원하는 동작을 쉽게 연결하여 사용할 수 있는 방법 확인!!

useImperativeHandle을 사용하여 편하게 동작도 가능하지만 useImperativeHandle 없이 props를 통해 직관적인 방법으로

필요한 기능을 전달하는 방법도 가능해요. 👍

 

 

✍️ 기록

 

감사합니다. 😁

 

반응형