TalentLayer Documentation
  • 👋Introduction
    • Value Proposition
    • Options for Integration
      • On-Demand Integration
      • Native Integration
    • TalentLayer's Functions
      • PlatformID
        • Fees & Economics
      • TalentLayerID
      • Reviews
      • Services
      • Escrow and Dispute
        • Dispute Workflow
        • Arbitration
          • Kleros Arbitration
          • Platform Managed Arbitration
    • Current Network Liquidity
    • Decentralization
  • ⚙️Technical Guides
    • Web 3 SDK & API
    • StarterKit Template
    • Technical Schemas
    • Network Support
    • Lower-Level Guides
      • Smart Contracts
        • Deployments
        • TalentLayerPlatformID.sol
        • TalentLayerID.sol
        • TalentLayerService.sol
        • TalentLayerReview.sol
        • Escrow & Dispute Contracts
      • The Graph
        • Introduction
        • Querying from an application
        • Queries examples
        • Implementing the pagination
      • Metadata
      • Third-Party Modules
        • Lens Protocol - Social
        • XMTP - Messaging
        • Sismo - Privacy
        • Iexec - Web3Mail
      • Messaging
        • Integrating XMTP
      • Standards
        • ERC-792: Arbitration standard
        • ERC-1497: Evidence Standard
      • How-To Guides
        • How to implement minting TalentLayer IDs?
        • How to implement the service creation?
        • How to implement the proposal creation?
        • How to implement the proposal validation?
    • Delegation
      • Meta Transaction
      • Delegate System
        • Setting
        • User workflow
        • Service creation example
        • How mintForAddress works
  • ⭐Get a Platform ID
  • 🧠Inspiration for Builders
  • 💬Contact The Team
  • 🦝Core Developer Guides
    • Subgraph Local Setup
    • Smart Contracts Local Setup
    • Advanced Documentation
    • Contract & Graph Deployment Guide
    • TalentLayer Improvement Proposals
    • Audit Report
Powered by GitBook
On this page
  • 1-Set and adapt your query
  • Other type of query for pagination
  • 2-Adapt your hook
  • 3-Set up the pagination in your component

Was this helpful?

  1. Technical Guides
  2. Lower-Level Guides
  3. The Graph

Implementing the pagination

In this guide, we'll explore how to implement pagination in your application using GraphQL queries. Pagination is essential for handling large data sets, providing a user-friendly way to navigate and interact with the information. We'll cover key concepts and techniques, enabling you to create efficient, scalable, and seamless user experiences with TalentLayer Graph

1-Set and adapt your query

export const getUsers = (
  numberPerPage?: number,
  offset?: number,
  searchQuery?: string,
): Promise<any> => {
  const pagination = numberPerPage ? 'first: ' + numberPerPage + ', skip: ' + offset : '';
  let condition = ', where: {';
  condition += searchQuery ? `, handle_contains_nocase: "${searchQuery}"` : '';
  condition += '}';

  const query = `
    {
      users(orderBy: rating, orderDirection: desc ${pagination} ${condition}) {
        id
        address
        handle
        userStats {
          numReceivedReviews
        }
        rating
      }
    }
    `;
  return processRequest(query);
};

The function first construct a pagination string based on the provided numberPerPage and offset parameters. If numberPerPage is not provided, the pagination string will be empty, which means that the query will fetch all users without pagination.

Next, the function constructs a conditional string that will be used in the GraphQL query to filter the users based on the provided searchQuery. If no searchQuery is provided, the conditional string will only contain an empty object.

Then we build the query with our two parameters => pagination and condition

Other type of query for pagination

As you can see in the query just below is that we add to parameter StartDate and EndDate that will allow us to set up a filter by date on our front end

export const getPaymentsForUser = (
  userId: string,
  numberPerPage?: number,
  offset?: number,
  startDate?: string,
  endDate?: string,
): Promise<any> => {
  const pagination = numberPerPage ? 'first: ' + numberPerPage + ', skip: ' + offset : '';

  const startDataCondition = startDate ? `, createdAt_gte: "${startDate}"` : '';
  const endDateCondition = endDate ? `, createdAt_lte: "${endDate}"` : '';

  const query = `
    {
      payments(where: {
        service_: {seller: "${userId}"}
        ${startDataCondition}
        ${endDateCondition}
      }, 
      orderBy: createdAt orderDirection: desc ${pagination} ) {
        id, 
        rateToken {
          address
          decimals
          name
          symbol
        }
        amount
        transactionHash
        paymentType
        createdAt
        service {
          id, 
          cid
        }
      }
    }
    `;
  return processRequest(query);
};

2-Adapt your hook

We add a few state variable and parameter in the useUsers hook

import { useEffect, useState } from 'react';
import { getUsers } from '../queries/users';
import { IUser } from '../types';

const useUsers = (
  searchQuery?: string,
  numberPerPage?: number,
): { hasMoreData: boolean; loading: boolean; users: IUser[]; loadMore: () => void } => {
  const [users, setUsers] = useState<IUser[]>([]);
  const [hasMoreData, setHasMoreData] = useState(true);
  const [loading, setLoading] = useState(false);
  const [offset, setOffset] = useState(0);

  useEffect(() => {
    setUsers([]);
    setOffset(0);
  }, [searchQuery]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await getUsers(numberPerPage, offset, searchQuery);

        if (offset === 0) {
          setUsers(response.data.data.users || []);
        } else {
          setUsers([...users, ...response.data.data.users]);
        }

        if (numberPerPage && response?.data?.data?.users.length < numberPerPage) {
          setHasMoreData(false);
        } else {
          setHasMoreData(true);
        }
      } catch (err: any) {
        // eslint-disable-next-line no-console
        console.error(err);
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, [numberPerPage, offset, searchQuery]);

  const loadMore = () => {
    numberPerPage ? setOffset(offset + numberPerPage) : '';
  };

  return { users, hasMoreData: hasMoreData, loading, loadMore };
};

export default useUsers;
  1. hasMoreData: This state variable is a boolean that indicates whether there are more users to fetch. It is initially set to true, which means that when the component is first rendered, it assumes there is more data to load. As data is fetched, this state variable will be updated based on the length of the fetched data. If the length of the fetched data is less than the specified numberPerPage, it sets hasMoreData to false, indicating that there are no more users to fetch. it allow you to display a button or a message.

  2. loading: This state variable is a boolean that indicates whether data is being fetched. It is initially set to false. it allow you to display a loader during the fetch process.

  3. offset: This state variable is a number that represents the pagination offset for the users list. It is initially set to 0. When the loadMore function is called, the offset is updated by adding the value of numberPerPage to the current offset. The updated offset is then used in the getUsers function to fetch the next set of users.

  4. numberPerPage is the element number you want to display per page, this parameter will be set in the component

3-Set up the pagination in your component

First we need to set up the parameter needed for useUsers call

const PAGE_SIZE = 36;

will the element number display per page

Then we call the hook useUsers and destructure the return object to get users, hasMoreData, loading and loadMore

const { users, hasMoreData, loading, loadMore } = useUsers(
    searchQuery?.toLocaleLowerCase(),
    PAGE_SIZE,
 );

You map your users oject and display all the data you want in a dedicated component.

 <div className='grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4'>
  {users.map((user, i) => {
    return <UserItem user={user} key={i} />;
   })}
 </div>

Then we add a button who call loadMore, you can check the hook useUsers with the loadMore function that will trigger setOffset.

<button
  type='submit'
  className={`......`}
  disabled={!hasMoreData}
  onClick={() => loadMore()}>
  Load More
</button>
PreviousQueries examplesNextMetadata

Last updated 2 years ago

Was this helpful?

Please find the code

Please find the code

Please find the code

⚙️
here
here
here