React 공식문서를 읽다보니 조금 생소한 훅이 있었다. 바로 useImperativeHandle
이라는 훅이다.
forwardRef를 공부하며, 봤던 훅인데 이번 기회에 한번 알아보자 ~
✅ 공식 문서
useImperativeHandle은 ref를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다.
항상 그렇듯이, 대부분의 경우 ref를 사용한 명령형 코드는 피해야 합니다. useImperativeHandle는 forwardRef와 더불어 사용하세요.
✅ forwardRef
forwardRef는 부모 컴포넌트에서 자식 컴포넌트로 자동으로 ref를 전달하여 부모가 자식 ref를 참조하는 기술이다,
✅ 코드
1️⃣ inputRef
라는 동아줄을 만들어서 자식에게 보내기
2️⃣ 자식 컴포넌트에 inputRef
넘기기
3️⃣ inputRef
받기 위하여 자식컴포넌트 forwardRef
감싸기
4️⃣ 참조할 태그에 ref
설정
5️⃣ 부모 컴포넌트에 존재하는 button
클릭으로 focus()
실행
6️⃣button
클릭으로 참조되던 자식 컴포넌트의 input
에 Focusing
function ParentComponent() {
const inputRef = useRef(); // 1️⃣ 번
return (
<>
<ChildrenCompenent ref={inputRef} /> // 2️⃣ 번
<button onClick={() => inputRef.current.focus()}>포커스</button> // 5️⃣ 번
</>
)
}
function ChildrenComponent(props, ref) {
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus(); // 6️⃣ 번
}
}));
return <input ref={inputRef} ... />; // 4️⃣ 번
}
ChildrenComponen = forwardRef(ChildrenComponen); // 3️⃣ 번
✅ 그래서 언제 사용?
분명 부모 컴포넌트에서 자식 컴포넌트 안 함수를 작동시켜야할 상황이 올 수 있다.
Why? 그냥 애초에 부모 컴포넌트에서 생성해놓고 자식 컴포넌트가 전달받으면 되잖아.
But, 만약 depth
가 깊은 컴포넌트 구조라면 Prop drilling
이 발생할 수 밖에 없다.
So, Redux
, Context API
등을 통해 전역으로 데이터를 전달하는 방식도 있지만, 굳이 그런 기술들을 사용하지 않을만큼이라면 useImperativeHandle
을 사용하는 것이 좋을 것 같다. 상태 또는 로직은 자식 컴포넌트가 갖고 있고, 부모 컴포넌트가 ref.current
에서 필요한 프로퍼티를 가져오기만 하면 되기 때문이다.
Warn, 기본적으로 리액트는 ref 사용을 크게 권장하지 않는다.
ref
를 통해 자식 컴포넌트 DOM요소
에 접근한다는 것은 자식 컴포넌트가 가진 DOM 노드
를 외부로 노출시키는 것이기 때문에 자식 컴포넌트의 캡슐화에 대한 장점을 없애는 것과 같기 때문이다.
🔗 Reference
👉 useImperativeHandle 공식문서
👉 useImperativeHandle?
👉 [React Hook] useImperativeHandle
👉 [React] useImperativeHandle의 장점