요약

초기 렌더링시 아직 데이터가 없기때문에 컴포넌트가 만들어지지 않았다. 그렇다고 이후 데이터가 들어왔다고 해서 ref 특성상 업데이트 되지 않았기 때문에 발생한 문제였고 아래와 같이 수정했다

 

업데이트없이 컴포넌트가 마운트됐을 때 값만 사용한다.

useRef === useState(value)[0]
{postListData && (
    <CardSection
      ref={scrollRef}
    >
       ...카드 데이터
    </CardSection>
)}
 <CardSection ref={scrollRef}>
     {postListData && (...카드 데이터)}
 </CardSection>

 

에러가 발생한 코드

블로그 메인을 개발하면서 드래그 앤 스크롤을 구현하기 위해 useRef를 사용해서 div elemnet를 가져왔고 react-use라이브러리의 useScroll을 통해 ref의 스크롤 위치 데이터 x를 가져오고자 했습니다. 이때 다른 컴포넌트에게 x값을 전달하여 현재 스크롤 위치에 따라 버튼을 활성화 시키고자 했습니다 

동작 예시
해당 버튼

const scrollRef = useRef<HTMLDivElement>(null);
const { x } = useScroll(scrollRef);
...

{postListData && (
    <CardSection
      ref={scrollRef}
    >
       ...카드 데이터
    </CardSection>
)}

문제는 처음 블로그 메인으로 접근했을 때 위 이미지 버튼쪽에서 스크롤 x값이 오지 않는다는게 문제였습니다. 하지만 위 이미지에서 다른 카드 페이지로 이동한 후 접근해봤을 땐 다시 정상적으로 동작하는 것을 확인하였습니다

 

해결 과정

  이후 useRef가 null인 이유에 대해 검색해보았고 stackoverflow에서 찾을 수 있었습니다.

https://stackoverflow.com/questions/56541342/react-hooks-why-is-current-null-for-useref-hook

 

React Hooks: Why is .current null for useRef Hook?

I have a simple example of a component: function App() { const observed = useRef(null); console.log(observed.current); return ( <div ref={observed} className="App"> <h1>

stackoverflow.com

이 외에도 조금 더 찾아보니 useRef는 렌더링 될 때 값을 받아오고 읽기전용이라 업데이트 되지 않으며 따라서 리렌더링을 발생시키지 않고 동작한다 등 여러가지 특징들을 살펴볼 수 있었습니다.

 

이후 문제가 생긴 제 코드를 좀 더 살펴본다면 CardSection 컴포넌트에서 scrollRef를 가져오는데, postListData 응답을 받아 데이터가 들어왔을 때 리액트에서 CardSection을 보여주게 됩니다.하지만 useRef는 앞서 작성했던 것처럼 초기 렌더링 될때만 값을 가져오고 리렌더링 된다고 해서 ref의 값이 업데이트 되진 않는데 초기 렌더링시 아직 데이터가 없기때문에 null로 설정되었지만 이후 데이터가 들어왔다고 해서 그 값이 업데이트 되지 않았기 때문에 발생한 문제였습니다

 

이후 다시 페이지로 접근헀을 때 됐던 이유는 데이터를 가져올 때 React-query, SWR같은 데이터 패칭 라이브러리를 사용하고 있어 캐시에 이미 저장된 값을 가져오게 되기 때문이며 해당 데이터 패칭방식을 변경한다면 똑같은 오류가 생기게 됩니다.

const scrollRef = useRef<HTMLDivElement>(null);
const { x } = useScroll(scrollRef);
...

{postListData && (
    <CardSection
      ref={scrollRef}
    >
       ...카드 데이터
    </CardSection>
)}

 

해결한 코드

<CardSection
    isdrag={isDrag} 
    ref={scrollRef}>
        {postListData && ...카드 데이터 ))}
</CardSection>

데이터가 없더라도 ref가 무조건 초기 렌더링시 렌더링 될 수 있도록 수정하였고 이후 데이터가 있는지 없는지 확인하는 코드를 안으로 집어넣도록 하였습니다. 이후 테스트 해본 결과 렌더링 시 카드 데이터와는 상관없이 무조건 초기 렌더링시 ref가 div element를 찾을 수 있게 되었고 문제를 해결하였습니다

 

회고

useRef가 use를 가지고 있어 useState 혹은 useEffect처럼 element가 불러와지면 자동으로 리렌더링 될줄 알고 상세 동작에 대해서 크게 생각하지 않았지만 이러한 특징을 알고 공부하게 된 좋은 계기가 되었습니다.
이후 제어 컴포넌트와 비제어 컴포넌트를 이해하게 된 계기가 되었습니다

복사했습니다!