Blog>
Snippets

Paginated Queries with React Query and TypeScript

Demonstrate how to implement server-side pagination in a React Query setup with TypeScript, including fetching, handling, and displaying paginated data.
interface PaginatedPosts {
  data: Post[];
  total: number;
  page: number;
  limit: number;
}

const fetchPaginatedPosts = async (page: number, limit: number = 10): Promise<PaginatedPosts> => {
  const response = await axios.get(`https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${limit}`);
  const total = parseInt(response.headers['x-total-count']);
  return {
    data: response.data,
    total,
    page,
    limit
  };
};
Defines the structure for the paginated posts and fetches them from the server. The 'fetchPaginatedPosts' function fetches a specific page of posts, using the _page and _limit query parameters, and returns both the data and pagination information.
const Posts: React.FC = () => {
  const [page, setPage] = useState(1);
  const { isLoading, isError, error, data } = useQuery<PaginatedPosts, Error>(['posts', page], () => fetchPaginatedPosts(page), {
    keepPreviousData: true
  });

  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error: {error.message}</div>;

  return (
    <div>
      {data?.data.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
      <button disabled={page === 1} onClick={() => setPage(old => Math.max(old - 1, 1))}>Previous Page</button>
      <button disabled={page * data.limit >= data.total} onClick={() => setPage(old => old + 1)}>Next Page</button>
    </div>
  );
};
Renders the paginated posts and provides buttons for navigating to the previous and next pages. It uses React Query's useQuery hook to fetch the data, enabling or disabling the navigation buttons based on the current page and total available pages.