Front-end/React & React Native

[Strapi + React] ApolloClient로 초간단 pagination 구현하기

대런대런 2020. 11. 18. 21:40
반응형

Strapi는 기본적으로 GraphQL을 지원한다.

 

Strapi - Open source Node.js Headless CMS 🚀

Strapi is the next-gen headless CMS, open-source, javascript, enabling content-rich experiences to be created, managed and exposed to any digital device.

strapi.io

 

React의 ApolloClient를 활용하여 API를 연동하고 있었기 때문에, pagniation도 내장기능을 사용하려 했다.

 

찾아보니 offset과 limit를 활용한 `offsetLimitPagination`이라는 헬퍼가 있었고, 적용해봤는데 생각대로 잘 되지 않았다...

www.apollographql.com/docs/react/pagination/offset-based/#the-offsetlimitpagination-helper

 

Offset-based pagination

A guide to using the Apollo GraphQL Client with React

www.apollographql.com

 

원인은 apollo에서 인식하는 파라미터인 `offset`은 Strapi에서 `start`라는 이름으로 처리하기 때문이었다.

 

파라미터 이름을 수정하는 기능은 따로 없어서 원본 코드를 따서 `offset`만 `start`로 변경해 주었다.

 

[원본코드 위치]

github.com/apollographql/apollo-client/blob/d470c964db46728d8a5dfc63990859c550fa1656/src/utilities/policies/pagination.ts#L25

 

최종코드 (함수명 : `startLimitPagination`)

import {
  FieldPolicy,
  Reference,
} from '@apollo/client';

type KeyArgs = FieldPolicy<any>['keyArgs'];

// A basic field policy that uses options.args.{start,limit} to splice
// the incoming data into the existing array. If your arguments are called
// something different (like args.{start,count}), feel free to copy/paste
// this implementation and make the appropriate changes.
export function startLimitPagination<T = Reference>(
  keyArgs: KeyArgs = false,
): FieldPolicy<T[]> {
  return {
    keyArgs,
    merge(existing, incoming, {args}) {
      const merged = existing ? existing.slice(0) : [];
      const start = args ? args.start : merged.length;
      const end = start + incoming.length;
      for (let i = start; i < end; ++i) {
        merged[i] = incoming[i - start];
      }
      return merged;
    },
  };
}

 

적용예시

const client = new ApolloClient({
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          posts: startLimitPagination(),
        },
      },
    },
  }),
});
반응형