SaltyCrane Blog — Notes on JavaScript and web development

Graphene and Relay example GraphQL pagination API and UI

beginning screenshot middle screenshot

This describes an example GraphQL API using Relay connections to power a discretely paged Amazon-like pagination UI. Connections are designed for infinite-scroll UIs, however Artsy Engineering developed a solution to use them with discretely paged UIs as described in their article: Effortless Pagination with GraphQL and Relay? Really!

I created a github repo with an implementation of the Artsy pagination API in Graphene, Django, and Python and a corresponding web app using Relay, React, and TypeScript.

For a vanilla Graphene Relay pagination API for an infinite scroll UI, see my basic example.

Graphene GraphQL backend

The Artsy pagination API augments the Relay Connection type with an additional pageCursors field that contains metadata used to implement the pagination UI. I ported their TypeScript code in artsy/metaphysics and relay-cursor-paging to Python using Graphene and Django.

Data is stored in a PostgreSQL database running in Docker. It is seeded with fish fixture data from ACNHAPI. Django is configured to log SQL queries to the console and show that SQL queries use COUNT, LIMIT, and OFFSET. Example:

SELECT COUNT(*) AS "__count" FROM "fishes_fish";
SELECT "fishes_fish"."id", "fishes_fish"."description", "fishes_fish"."icon_url", "fishes_fish"."name", "fishes_fish"."price" FROM "fishes_fish" ORDER BY "fishes_fish"."name" ASC LIMIT 5 OFFSET 5;
  • Install Python 3.8

  • Install packages, set up database, and run dev server

    $ git clone https://github.com/saltycrane/graphene-relay-pagination-example.git
    $ cd graphene-relay-pagination-example
    $ cd graphene-api
    $ python3 -m venv venv
    $ source venv/bin/activate
    $ pip install -r requirements.txt
    $ docker-compose up -d
    $ ./bin/resetdb
    $ ./manage.py migrate
    $ ./manage.py loaddata fishes
    $ ./manage.py runserver
    
  • Go to http://127.0.0.1:8000/graphql/ in the browser

  • Run the following query:

    {
      allFishes(first: 5, orderBy: "name") {
        pageCursors {
          previous {
            cursor
          }
          first {
            cursor
            page
          }
          around {
            cursor
            isCurrent
            page
          }
          last {
            cursor
            page
          }
          next {
            cursor
          }
        }
        edges {
          cursor
          node {
            name
          }
        }
      }
    }
    GraphiQL query screenshot
    graphiql screenshot
Generate a GraphQL schema
$ ./manage.py graphql_schema --schema pagination_ex_api.schema.schema --out ../schema.graphql

React Relay Next.js frontend

In addition to Relay, React, and TypeScript, the frontend UI uses relay-hooks, Next.js, and reactstrap. It takes advantage of Relay fragments and Next.js routing to store pagination state. Server-side rendering (SSR) is disabled because it's difficult to set up and isn't important for this example.

  • Install Node.js 14

  • Install packages and run dev server

    $ cd react-relay-webapp
    $ npm install
    $ npm run devserver
    
  • Go to http://127.0.0.1:3000 in the browser

My backend codeMy frontend codeExternal TypeScript codeExternal Python code

Comments