[Book Buddy / Error Note] React component에서 forwardRef로 ref prop 적용하기

스크롤 조작 때문에 Dom에 접근하기 위해 useRef 한 번 사용해 보려다가 삽질 좀 했다.

 

1.  ref 적용시 에러

ref를 일반 props로 인식하나보다. 찾아보니 함수형 컴포넌트는 ref를 그냥 사용 할 수 없다고 한다.

import React, { useEffect, useRef } from 'react';

const Mypage = () => {
  const scrollRef = useRef();
  useEffect(() => {
    // (스크롤 조작 관련 코드)
  });
  return (
    <Styled_Layout.Container> 
        // ...중략...
              <Styled_Mypage.Books ref={scrollRef}> //ref 사용     
        // ...중략...
    </Styled_Layout.Container>
  );
};

export default Mypage;

 

"ref를 props로 넘기려면 ref를 넘기려는 React component를 forwardRef()로 감싸주면 함수는 ref라는 매개변수를 갖게 되는데 그 매개변수에 prop을 넘길 수 있다."
출처: https://lulu-developmentlog.tistory.com/274

그렇다고 한다.

 

일단 아래처럼 forwardRef로 컴포넌트를 감싸주었다.

 

import React, { forwardRef, useEffect, useRef } from 'react';

const Mypage = forwardRef<HTMLDivElement>((props, ref) => {
  const scrollRef = useRef();
  useEffect(() => {
    // (스크롤 조작 관련 코드)
  });
  return (
    <Styled_Layout.Container> 
        // ...중략...
              <Styled_Mypage.Books ref={scrollRef}> //ref를 props로 넣어주는 부분     
        // ...중략...
    </Styled_Layout.Container>
  );
});

export default Mypage;

 

 

2.  eslint 에러

Component definition is missing display name

 

짠.. 1번을 완료하면 이렇게 eslint 에러를 만날 수 있다. 디버깅때문에 생기는 에러인 듯 하다.

 

스텍오버플로우를 보니 크게 세 가지 방법이 있는 것 같았다.

 

첫 번째는 displayName을 직접 지정하는 것이다.

ComponentName.displayName = "ComponentName" 으로 지정해주면 된다.

import React, { useEffect, useRef } from 'react';

const Mypage = React.forwardRef<HTMLDivElement>((props, ref) => {
  const scrollRef = useRef();
  useEffect(() => {
    // (스크롤 조작 관련 코드)
  });
  return (
    <Styled_Layout.Container> 
        // ...중략...
              <Styled_Mypage.Books ref={scrollRef}> // ref 사용   
        // ...중략...
    </Styled_Layout.Container>
  );
});

Mypage.displayName = 'Mypage';
export default Mypage;

 

 

두 번째는 export에서 컴포넌트를 forwardRef로 감싸는 방법이다. 

스택오버플로우에 있는 코드를 그대로 따라했더니 타입 에러가 나서 ForwardedRef를 import하여 타입을 따로 지정해줬다.

import React, { ForwardedRef, forwardRef, useEffect, useRef } from 'react';

const Mypage = (props: any, ref: ForwardedRef<HTMLDivElement>) => {
  const scrollRef = useRef();
  useEffect(() => {
    // (스크롤 조작 관련 코드)
  });
  return (
    <Styled_Layout.Container> 
        // ...중략...
              <Styled_Mypage.Books ref={scrollRef}> // ref 사용   
        // ...중략...
    </Styled_Layout.Container>
  );
});

export default forwardRef(Mypage);

 

마지막 방법은 component function 안에 다시 function을 정의해주는 방법이다.

함수 이름을 두 개나 작성해야 해서 개인적으로 마음에 드는 방법은 아니었다.

const Mypage = forwardRef<HTMLDivElement>(function Mypage2(props, ref) {
	// ...중략...
});

 

 

 

그래서 무엇을 사용했냐. 

import 개수가 적고 코드 길이도 짧은 1번을 사용하고 싶었다.

사용하고 싶었... 는데 여러가지 방법을 실험하는 도중 갑자기 문제가 해결되었다. 분명 처음 코드와 거의 동일한데 ref is not prop 에러가 안 뜨게 되어서 열심히 공부하고 그냥 useRef를 사용했다. 무엇이 바뀐 건지 알고싶은데 아직 원인을 못 찾았다. 

 

 

 

 


 

참고자료

 

https://lulu-developmentlog.tistory.com/274

https://kjwsx23.tistory.com/493

https://stackoverflow.com/questions/67992894/component-definition-is-missing-display-name-for-forwardref