useInfiniteQuery 로 무한스크롤 구현하기-(2)

가연·2023년 10월 16일
1

admin의 구조는
AdminForm > Title + AdminBox > RequestContainerBox 2개 > 컨테이너 css 구조 ...

로 되어있다. 따라서 2개의 컨테이너를 나눠서 무한스크롤을 적용하려면 각각 useRef로 bottom 을 지정해주어야 한다. 그렇게 하려면 RequestContainerBox 컴포넌트 내부에 접근해야 하는데,AdminBox에서 forwardRef 를 사용하여 하위 컴포넌트에 ref를 적용했다.

AdminBox.jsx 의 기본 정보 요청 무한스크롤


const Data1 = data1?.pages.flatMap((x) => x.data.response);
const DataArr1 = Data1 || [];
 <RequestContainerBox
        border=" 2px solid #F5F6FA;"
        title="정보 수정 요청"
        data={DataArr1}
        route={routes.basicInfoEditRequest}
        modi={true}
        isLoading={isLoading1}
        error={error1}
        ref={bottomObserver1}  //✅
        isError={isError1}
      ></RequestContainerBox>

RequestContainerBox.jsx


const RequestContainerBox = React.forwardRef( ✅
  ({ title, border, data, route, modi, isLoading, error, isError }, ref) => {
    return (
      <RequestContainerBoxCss>
        <TitleBox
          title={title}
          isLoading={isLoading}
          error={error}
          isError={isError}
        />
        <RequestContain
          border={border}
          datas={data}
          route={route}
          modi={modi}
          isLoading={isLoading}
          error={error}
        >
          {!isLoading && <Bottom ref={ref}>. </Bottom>} ❌
        </RequestContain>
      </RequestContainerBoxCss>
    );
  }
);

RequestContainerBox.displayName = "RequestContainerBox"; ✅ ❌

✅ 가 forwardRef 를 사용한 부분이다.

❌ 아래는 사용하는데 생긴 두개의 에러사항을 해결한 것이다.

displayName

forwardRef 를 사용 도중

error Component definition is missing display name react/display-name

위와 같은 eslint 에러가 났다.

const hello = function()
  {
    console.log("Hello");
  };

이와 같은 함수를 익명함수 라고 하는데, 익명함수는 크롬 브라우저에서 디버깅 한 결과를 보면 이름이 나오지 않게 된다.

forwardRef() 함수를 호출할 때 익명 함수를 넘기게 되면 브라우저에서 디버깅 시 함수의 이름을 알 수 없게 되고, 에러가 날 수 있는 위험이 있다.
다음은 forwardRef 를 사용할 때 함수 이름이 나올 수 있게 하는 방법이다.

1️⃣ forwardRef() 함수에 익명 함수를 대신에 이름이 있는 함수 넘기기.

const RequestContainerBox = forwardRef(function Input(props, ref) {
  return <RequestContainerBox type="text" ref={ref} />;
});

2️⃣ forwardRef() 함수의 호출 결과로 기존 컴포넌트를 대체.

function RequestContainerBox(props, ref) {
  return <input type="text" ref={ref} />;
}

RequestContainerBox = forwardRef(RequestContainerBox);

3️⃣ displayName 으로 컴포넌트에 이름 설정하기

const RequestContainerBox = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />;
});

RequestContainerBox.displayName = "RequestContainerBox";

다음 페이지 호출할 때 로더가 적용되지 않는 문제

첫 화면에서는 로더가 이렇게 잘 출력이 되는데, 다음 페이지 호출할 때는 로더가 생기지 않았다.

tenstack공식페이지 에 있는 무한스크롤 예제에서 다음 페이지를 호출할때 fetching 상태가 됐다. 그래서 코드를 아래로 수정했더니 로더가 잘 출력되었다.
{(isLoading || isFetching) && <Loader></Loader>}

그러면 왜 다음페이지를 요청할때만 fetcing 상태가 될까?

isLoading은 서버에 데이터 요청을 처음 할 때
isFetching은 서버에 데이터 요청을 다시 할 때 (캐시된 데이터가 있을 때)

라고 한다.

자세히 말하자면 isLoading = isFetching + 쿼리에 캐시된 데이터가 없을때 라서 isLoading은 처음 데이터를 요청할때 쓰이고, isFetching은 서버에 요청을 다시 할 때 사용한다고 한다.

그러면 내가 작성한 코드를 예로 들자면 첫 요청 시 로딩 상태이며, 데이터들을 가져온다. 다음 페이지를 요청할때는 앞에 데이터를 요청했었기 때문에 캐시된 데이터가 존재하며, 그 데이터는 디폴트 설정을 안해줬기 때문에 바로 stale 한 상태가 된다. 그리고 캐시된 데이터가 있는상태에서 요청했기 때문에 패칭 상태가 된다.

리액트 쿼리의 장점 중 하나가 캐싱을 이용할 수 있다는 점인데 캐싱을 하나도 이용을 안하고 있다는걸 깨달았다.. 추후에 리팩토링으로 캐싱된 데이터를 이용하는 방법과 초기설정에 대해 공부해봐야겠다.


레퍼런스

0개의 댓글