본문 바로가기

dev/React

react 자식 컴포넌트의 함수를 부모 컴포넌트에 내보내기

가끔 react에서 자식 컴포넌트의 함수를 부모 컴포넌트로 내보내야 할 때가 있습니다.

좋은 패턴은 아니지만 필요하다면 useImperativeHandle을 사용하면 됩니다.

 

useImperativeHandle의 특징은 공식 문서 한글 번역이 굉장히 난해하다는 점입니다. 아마 쓰지 말라는 무언의 암시가 아닐까 생각합니다. 공식 문서에서 제공하는 번역은 다음과 같습니다.

useImperativeHandle은 ref를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다. 

다행히 원문은 아래와 같습니다.

useImperativeHandle customizes the instance value that is exposed to parent components when using ref

자신의 인스턴스 변수를 부모 컴포넌트에 노출시킬 때 사용하는 것이 useImperativeHandle입니다.

자바스크립트는 변수에 함수를 할당할 수 있기 때문에 함수 또한 변수로써 노출이 가능합니다.

 

그럼 이 변수의 레퍼런스는 누가 받을까요?

보통 리액트에서 이런 리액트스럽지 않은 변수들은 대부분 ref가 받습니다.

ref를 검색하면 dom node를 받는 경우가 많이 검색되는 이유가 이것 때문입니다.

어쨌든 자식 컴포넌트에서는 부모 컴포넌트가 ref를 받을 수 있도록, ref를 공개해 주면 됩니다.

forwardRef를 통해서요!

 

쉽게 말해 ref가 매개체 역할입니다.

부모 컴포넌트는 자식 컴포넌트에게 ref를 건네주고,

자식 컴포넌트는 부모님에게 받은 ref에 자기가 만든 함수를 등록하는 것입니다.

 

그러면 부모 컴포넌트에서는 자식이 등록해 준 함수를 사용할 수 있는 것이구요.

 

정리하자면,

자식 컴포넌트의 함수를 부모 컴포넌트에서 사용하기 위해서는 useImperativeHandle을 사용하면 됩니다.

그리고 실제 구현하는 방법은 아래와 같습니다. 공식 문서의 예제를 변형했습니다.

... /FancyParent.js
function FancyParent(anything){
    const fancyRef = useRef(null)
    const onClickParent = (e) => {
    	ref.current.focus()	// 부모 컴포넌트에서 자식의 focus 함수 호출 가능!
    }
    
    return (
    	<FancyInput ref={fancyRef} onClick={onClickParent}/>
}

... /FancyInput.js
function FancyInput({ others, ...props }, ref) {
  // focus 함수를 ref 통해 외부로 내보냄
  useImperativeHandle(ref, () => ({
    focus: () => {
     ...
  }));
  return <input {...props}/>;
}

const FancyInputWithRef = ((props,ref)=>forwardRef(FancyInput))
export { FancyInputWithRef as FancyInput }