Remix

How to Get Shopify Store all Product using Pagination in Shopify Remix?

In this article, we will learn about how to get Shopify store all products using pagination in Shopify Remix.

Introduction:

Pagination allows you to retrieve a large number of products without overwhelming system resources or hitting API rate limits. By fetching a limited number of products per request, you can efficiently manage large datasets.

Fetching products in smaller batches reduces the overall latency of the request. Instead of waiting for a single large response, you can start processing the data as soon as each page is received, leading to a smoother user experience.

Retrieving products in batches reduces the memory footprint of your application. You don’t need to store the entire dataset in memory at once, which is especially important for applications running on devices with limited resources.

Pagination can improve the performance of your application by distributing the workload across multiple requests. This can help prevent timeouts and ensure that your application remains responsive, even when dealing with large amounts of data.

Steps to Implement Pagination in Shopify to Get all Products:

Step 1: First of all, create app.pagination route file in your app -> routes directory.

Step 2: Get all products using GraphQL.

For example

import { useLoaderData, Form, Link, useNavigate } from "@remix-run/react";
import shopify from "app/shopify.server";
import { json } from "@remix-run/node";
import { Page, IndexTable, Card, Pagination } from "@shopify/polaris";
import { useMemo} from "react";

export async function loader({ request }) {
  const { admin } = await shopify.authenticate.admin(request);
  const url = new URL(request.url);
  const searchParam = url.searchParams;
  const rel = searchParam.get('rel');
  const cursor = searchParam.get('cursor');
  let searchString = `first: 5`;
  if(cursor && rel) {
    if(rel == "next") {
      searchString += `, after: "${cursor}"`;
    } else {
      searchString = `last: 5, before: "${cursor}"`;
    }
  }
  const response = await admin.graphql(`
    {
      products(${searchString}) {
        pageInfo {
          endCursor
          hasNextPage
          hasPreviousPage
          startCursor
        }
        nodes {
          id
          title
          description
          status
          images(first: 1) {
            edges {
              node {
                originalSrc
                altText
              }
            }
          }
        }
      }
    }`);
  const parsedResponse = await response.json();
  const product = parsedResponse.data.products.nodes;
  const pageInfo = parsedResponse.data.products.pageInfo;

  return json({ product, pageInfo });
}

In this loader function admin is destructured from the result of calling shopify.authenticate.admin(request). This likely returns an authenticated Shopify admin API instance.

The loader function extracts the query parameters rel and cursor from the request URL using URLSearchParams. These parameters likely indicate the direction of pagination (rel: “next” or “previous”) and the cursor (pagination token) for fetching the next or previous set of products.

Based on the rel and cursor parameters, the function constructs a GraphQL query string (searchString) to fetch products. If cursor and rel are present, it adds pagination parameters (after or before) to the GraphQL query to retrieve the next or previous set of products.

The function sends a GraphQL query to the Shopify admin endpoint using the admin.graphql method. The query fetches product data, including id, title, description, status, and the first image’s originalSrc and altText.

Pagination information (pageInfo) is also requested, including endCursor, hasNextPage, hasPreviousPage, and startCursor.

The response is parsed as JSON. Product data (product) and pagination information (pageInfo) are extracted from the parsed response.The function returns the product data and pagination information wrapped in a JSON response using json().

Step 3: Create a Shopdata function to render the product data from the loader function.

export default function Shopdata() {
    const { product, pageInfo} = useLoaderData();
    const navigate = useNavigate();
    const pagination = useMemo(() => {
        const { hasNextPage, hasPreviousPage, startCursor, endCursor } =  pageInfo || {};

      return {
            previous: {
                disabled: !hasPreviousPage || !startCursor,
                link: `/app/shopifydata/?rel=previous&cursor=${startCursor}`,                  
            },
          next: {
              disabled: !hasNextPage || !endCursor,
              link: `/app/shopifydata/?rel=next&cursor=${endCursor}`,
           },
      };
  }, [pageInfo]);

         const rowMarkup = product.map(
              ({ images, id, title, description, status }, index) => (

            <IndexTable.Row id={id} key={id} position={index}>
                  <IndexTable.Cell>
                    <img  style={{ width: "30px", height: "40px" }} src={images.edges[0].node.originalSrc}
                alt={images.edges[0].node.altText} />
                </IndexTable.Cell>

              <IndexTable.Cell> {id.replace("gid://shopify/Product/", "")} </IndexTable.Cell>
              <IndexTable.Cell> {title} </IndexTable.Cell>
              <IndexTable.Cell> {description} </IndexTable.Cell>
              <IndexTable.Cell> {status} </IndexTable.Cell>
         </IndexTable.Row>
               )
        );
   return (
                 <Page>
             <Card>
                         <IndexTable
                             itemCount={product.length}
                             headings={[
                            { title: "Image" },
                            { title: "Id" },
                            { title: "Title" },
                            { title: "Description" },
                            { title: "Status" },
                          ]}
                          selectable={false}
                       >
                  {rowMarkup}
                  </IndexTable>
            <div className="navigation">
                  <Pagination
                                hasPrevious={!pagination.previous.disabled}
                                onPrevious={() =>navigate(pagination.previous.link)}
                                hasNext={!pagination.next.disabled}
                                onNext={() => navigate(pagination.next.link)}
                 />
            </div>
                </Card>
</Page>
   );
}

Destructuring Loader Data using the useLoaderData hook to extract product and pageInfo from the data loaded by the loader function. This data likely contains the product details and pagination information.

Navigation Setup using the useNavigate hook to get the navigate function, which will be used for navigating between pagination pages.

Pagination Calculation using the useMemo hook to calculate pagination details based on the pageInfo. It checks whether there are previous and next pages available based on the hasPreviousPage and hasNextPage properties in pageInfo. It constructs the pagination links (previous and next) with the appropriate cursor values for fetching the previous or next set of products.

 Pagination Controls renders a Pagination component from the Shopify Polaris UI library.

The Pagination component is provided with props indicating whether there are previous and next pages (hasPrevious and hasNext) and functions to handle navigation (onPrevious and onNext). The disabled state of the pagination controls is determined by the pagination calculation performed earlier.

Overall Rendering The component returns a Page component wrapping a Card component.

Conclusion:

In conclusion, pagination is an essential tool for optimizing Shopify stores. By dividing large datasets into manageable chunks, it enhances website performance, improves user experience, and makes it easier for visitors to navigate through the store’s products. With Shopify Remix, store owners can customize their pagination settings to fit their specific needs, ensuring that their website remains fast, responsive, and user-friendly. Whether you have a small or large store, implementing pagination in Shopify Remix can help you improve your website’s performance and provide a better user experience for your customers.

Click to rate this post!
[Total: 2 Average: 5]
Bharat Desai

Bharat Desai is a Co-Founder at MageComp. He is an Adobe Magento Certified Frontend Developer 🏅 with having 8+ Years of experience and has developed 150+ Magento 2 Products with MageComp. He has an unquenchable thirst to learn new things. On off days you can find him playing the game of Chess ♟️ or Cricket 🏏.

Recent Posts

Magento 2: Add Quantity Increment and Decrement on Category Page

Hello Magento Friends, In this blog, we will discuss about adding quantity increment and decrement…

2 days ago

How to Integrate ChatGPT with Laravel Application?

In this guide, we'll explore how to integrate ChatGPT, an AI-powered chatbot, with a Laravel…

5 days ago

What are Net Sales? How to Calculate Your Net Sales?

In the world of business, understanding financial metrics is crucial for making informed decisions and…

1 week ago

Magento 2 Extensions Digest April 2024 (New Release & Updates)

Welcome to the MageComp Monthly Digest, where we bring you the latest updates, releases, and…

1 week ago

The ABCs of Geofencing: Definition, Features and Uses

In this era, businesses are always on the lookout for ways to engage with their…

1 week ago

How to Delete Product Variant in a Shopify Remix App using GraphQL Mutations?

Managing a Shopify store efficiently involves keeping your product catalog organized. This includes removing outdated…

1 week ago