useImperativeHandle
은 ref
로 노출되는 핸들을 커스터마이징할 수 있도록 해주는 리액트 훅이에요.
useImperativeHandle(ref, createHandle, dependencies?)
Reference | 레퍼런스
useImperativeHandle(ref, createHandle, dependencies?)
노출된 ref 핸들을 커스터마이징하려면 최상위 컴포넌트에서 useImperativeHandle
을 호출하세요.
import { forwardRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);
// ...
}
더 많은 예시는 아래를 확인하세요.
Parameters | 파라미터(매개변수)
ref
:forwardRef
렌더 함수에서 두 번째 인자로 받은ref
createHandle
: 어떤 인자도 받지 않고 노출하고 싶은 ref 핸들을 반환하는 함수. 해당 ref 핸들은 어떤 타입이든 될 수 있어요. 보통은 노출하고 싶은 메서드를 갖고 있는 객체를 반환할 거예요.dependencies
(선택사항) :createhandle
코드 내부에서 참조하는 반응값 목록. props, 상태 그리고 컴포넌트 바디 안에서 직접적으로 선언된 모든 변수와 함수는 반응값에 포함돼요. 만약 린터가 리액트에 맞춰져있다면, 모든 반응값이 의존성으로 알맞게 지정되어 있는지 확인해요. 의존성 목록은 상수개의 아이템을 갖고 있어야만 하고[dep1, dep2, dep3]
고 같은 인라인 형태로 작성되어 있어야해요. 리액트는 각각의 의존성을Object.js
비교를 사용하여 이전의 값과 비교해요. 만약 리렌더링이 일부 의존성을 변경하는 결과를 초래한다면, 또는 이 인자를 생략했다면,createHandle
함수는 재실행 될것이고, 새롭게 생성된 핸들은 ref에 할당될 거예요.
Returns | 반환값
useImperativeHandle
은 undefined
를 반환해요.
Usage | 용법
Exposing a custom ref handle to the parent component | 부모 컴포넌트로 커스텀한 ref 핸들 노출하기
기본적으로, 컴포넌트는 그들의 DOM 노드를 부모 컴포넌트에게 노출하지 않아요. 예를 들어, MyInput
의 부모 컴포넌트가 <input>
DOM 노드에 접근하고 싶다면 forwardRef
를 사용해서 선택해야해요.
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});
위의 코드와 함께 <MyInput>
으로의 ref는 <input>
DOM 노드를 받을 거예요. 그러나 대신에 커스텀 된 값을 노출할 수도 있어요. 노출된 핸들을 커스터마이징하려면 useImperativeHandle
을 최상위 컴포넌트에서 호출하세요.
import { forwardRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);
return <input {...props} />;
});
위의 코드에서 ref
는 <input>
으로 더 이상 전달되지 않는다는 것을 명심하세요.
예를 들어, <input>
DOM 노드 전체를 노출하고 싶지 않지만 메서드 중 focus
와 scrollIntoView
만 노출하고 싶다고 생각하세요. 이를 위해서, 실제 브라우저 DOM을 분리된 ref로 유지해야해요. 그 다음, useImperativeHandle
을 사용하여 부모 컴포넌트에서 호출하고 싶은 메서드만을 사용하여 handle을 노출해야해요.
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} />;
});
이제, 만약 부모 컴포넌트가 <MyInput>
ref를 얻고 싶다면 ref에 있는 focus
와 scrollIntoView
메서드를 호출할 수 있어요. 그러나 이것은 실제 <input>
DOM 노드에 완전히 접근할 수는 없어요.
Exposing your own imperative methods | 자체적인 명령형 메서드 노출하기
명령형 핸들을 통해 노출한 메서드는 DOM 메서드와 정확히 일치할 필요가 없어요. 예를 들어 이 Post
컴포넌트는 scrollAndFocusAddComment
메서드를 명령형 핸들을 통해 노출했어요. 이는 부모 Page
가 댓글 리스트를 스크롤하고 버튼을 클릭할 때 인풋 영역에 포커스 되도록 만들어요.
함정
ref를 남용하지 마세요. 노드 스크롤링하기, 노드 포커싱하기, 애니메이션 트리거하기, 텍스트 선택하기와 같은 행동 같이 props로 표현할 수 없는 명령형 행동이 필요할 때만 ref를 사용하세요.
만약 props로 무언가를 표현할 수 있다면 ref를 사용하면 안돼요. 예를 들어,Modal
컴포넌트의{ open, close }
와 같은 명령형 핸들을 노출하는 대신<Modal isOpen={isOpen} />
과 같이 prop으로isOpen
을 갖고 있는게 더 좋아요. 이펙트는 props를 통해 명령형 행동을 노출하는 것을 도와줄 거예요.
'리액트 공식문서 | React Docs > Reference > react@18.2.0' 카테고리의 다른 글
[Hooks] useLayoutEffect | useLayoutEffect 훅 (1) | 2024.01.25 |
---|---|
[Hooks] useInsertionEffect | useInsertionEffect 훅 (0) | 2024.01.25 |
[Hooks] useId | useId 훅 (0) | 2024.01.21 |
[Hooks] useEffect | useEffect 훅 (0) | 2024.01.18 |
[Hooks] useDeferredValue | useDeferredValue 훅 (1) | 2024.01.14 |