본문 바로가기
배움 기록/React

[React] forwardRef 사용법 (useRef, useImperativeHandle...)

by dygreen 2023. 2. 5.
(함수형 컴포넌트에서)
부모 컴포넌트에서 자식 컴포넌트 안의 DOM element에 접근하고 싶다면?
forwardRef를 사용해야 한다.

 

 

회사에서 프로젝트를 진행하던 중, 부모 컴포넌트에서 자식 컴포넌트 안의 함수를 사용해야 하는 경우가 생겼다.

자식 컴포넌트에서 부모 컴포넌트의 함수를 사용하려면 props를 사용하면 되었지만

그 반대의 경우는 경험해 본 적이 없어서 어떤 방식이 있는지 찾아보다 forwardRef라는 Hook을 발견하였다.

 

 

📌 forwardRef를 사용해야 하는 이유 ?

  • 함수형 컴포넌트는 인스턴스가 없기 때문에 ref 속성을 사용할 수 없다.
  • 따라서, 함수형 컴포넌트를 forwardRef로 감싸주게 되면 ref를 사용할 수 있다.
  • (+ 클래스로 선언된 컴포넌트들은 인스턴스를 가지기 때문에 ref 속성 사용 가능)
  • 부모 컴포넌트에서 자식 컴포넌트 안의 DOM element에 접근하고 싶을 때 사용한다.

 

 

📌 [참고] useRef ?

forwardRef를 사용하는 방법에 대해 설명하기 전에, useRef라는 Hook에 대한 개념 이해가 필요하다.

 

useRef는 DOM element에 직접 접근하기 위해 사용하는 Hook이다.

왜 useRef를 통해 DOM element에 접근해야 하냐면, 

React는 가상돔을 기반으로 작동하는 라이브러리이기 때문이다.

 

컴포넌트가 mount될 때 React는 current 프로퍼티에 DOM element를 대입하고,

컴포넌트가 unmount될 때 프로퍼티를 다시 null로 돌려놓는다.

실제 DOM에 React 노드가 렌더될 때까지 ref가 가리키는 DOM element의 주소 값은 확정된 것이 아니다.

 

 

📌 forwardRef 사용법

1. 부모 컴포넌트에서 useRef()를 선언하고, 자식 컴포넌트에 보낸다.

import { useRef } from 'react'
import Child from './Child'

const Parent = () => {
  const compRef = useRef()
  
  return (
    <Child ref={compRef} />
  )
}

export default Parent;

 

 

2. 자식 컴포넌트를 forwardRef()로 감싸고, 부모에서 사용할 함수를 useImperativeHandle()로 감싼다.

import { forwardRef, useImperativeHandle } from 'react'

const Child = forwardRef((props, ref) => {
  // 부모 컴포넌트에서 사용할 함수 설정
  useImperativeHandle(ref, () => ({
    req1,
    req2
  }))
  
  // 함수 1
  const req1 = () => { }

  // 함수 2
  const req2 = () => { }
}

export default Child

 

forwardRef()

  • 자식 컴포넌트를 forwardRef로 감쌌을 때, 2번째 매개변수인 ref부모 컴포넌트가 props로 넘긴 값(=compRef)이다.

useImperativeHandler()

  • useImperativeHandler첫 번째 인수로는 부모 컴포넌트가 props로 넘긴 ref를 전달한다.
  • 두 번째 인수로는 콜백함수를 전달한다. ( 콜백함수의 반환값이 바로 부모 컴포넌트 내 useRef Hook 호출시 반환된 객체의 current 프로퍼티에 바인딩될 값이 된다. )

 

 

3. 부모 컴포넌트에서 current 프로퍼티를 통해 함수를 사용한다.

import { useRef } from 'react'
import Child from './Child'

const Parent = () => {
  const compRef = useRef()
  
  const fnReqBtn1 = e => {
    e.preventDefault();

    compRef.current.req1();
  }

  const fnReqBtn2 = e => {
    e.preventDefault();

    compRef.current.req2();
  }
  
  return (
    <>
      <Child ref={compRef} />
      <Link onClick={fnReqBtn1}>가입버튼1</Link>
      <Link onClick={fnReqBtn2}>가입버튼2</Link>
    </>
  )
}

export default Parent;

 


참고 :
https://ko.reactjs.org/docs/forwarding-refs.html
https://ko.reactjs.org/docs/hooks-reference.html#useref
https://tecoble.techcourse.co.kr/post/2021-05-15-react-ref/
728x90

댓글