[React] ref 전달하기
React에서 자식 컴포넌트에 ref를 전달하려고 하면 오류가 발생한다.
1 | import { useRef, useEffect } from 'react' |
위 코드를 실행하면 의도한대로 동작하지 않는 것을 볼 수 있다.
이런식으로 가리키게 하려고 한 것이나 실패한다. warning은 다음과 같다.
1 | Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? |
warning에도 나와있듯 이런 경우 forwardRef
를 사용해야한다.
forwardRef
foreardRef
는 고차원 컴포넌트에서 ref를 전달할 때 사용한다. ref를 전달받고자 하는 하위 컴포넌트를 forwardRef
로 감싸면 된다.
1 | import { useRef, useEffect, forwardRef } from 'react' |
forwardRef
컴포넌트는 첫번째 인자로 props를 받고 전달 받은 ref는 두 번째 인자로써 처리한다.
Typescript에서 사용하기
Typescript에서는 타입지정 때문에 에러가 계속 발생했다.
1 | import { useRef, useEffect, forwardRef } from 'react' |
이런 식으로 작성한 코드에서 current
부분에 계속 에러가 발생했다.
1 | Property 'current' does not exist on type 'Ref'. Property 'current' does not exist on type '(instance: HTMLDivElement) => void' |
구글링을 해보니 Ref가 항상 current
프로퍼티를 가지는 object 인 게 아니라서 발생하는 오류였다. Ref가 함수가 될 수도 있기 때문에 ref.current
구문에서 타입 에러가 발생하는 것이다. Stackoverflow에서 간단한 훅을 발견해서 나는 이렇게 해결했다.
useForwardRef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const useForwardRef = <T,>(
ref: ForwardedRef<T>,
initialValue: any = null
) => {
const targetRef = useRef<T>(initialValue);
useEffect(() => {
if (!ref) return;
if (typeof ref === 'function') {
ref(targetRef.current);
} else {
ref.current = targetRef.current;
}
}, [ref]);
return targetRef;
};index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import { useRef, useEffect, forwardRef } from 'react'
export function Parent() {
const elementRef = useRef()
useEffect(() => {
// Does not work!
console.log(elementRef.current) // logs <div>Hello, World!</div>
}, [])
return <Child ref={elementRef} /> // assign the ref
}
const Child = forwardRef((props, ref) => {
const btnRef = useForwardRef<HTMLButtonElement>(ref);
const hadler = () => {
btnRef.current?.open();
}
return <button onClick={handler}>Button</button>
})
이런식으로 current
를 문제 없이 사용할 수 있었다.
참고
이 블로그의 모든 글은 CC BY-NC-SA 4.0 라이선스를 따르며, 별도로 명시되지 않는 한 모든 권리를 보유합니다. 재배포 시 출처를 명시해 주세요: StudyYeong.