Pagination and Sorting With searchCriteria
Pagination and Sorting With searchCriteria
~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
Loading 247 products at once would be neither fast nor sensible to display – time to use searchCriteria properly: paging through results and sorting by field.
The key searchCriteria parameters
searchCriteria[pageSize]– how many products per page (already used since chapter 7).searchCriteria[currentPage]– which page, starting at1(NOT0!).searchCriteria[sortOrders][0][field]– which field to sort by, e.g.nameorprice.searchCriteria[sortOrders][0][direction]–ASCorDESC.
Extending fetchProducts() with pagination and sorting
const BASE_URL = import.meta.env.VITE_MAGENTO_BASE_URL;
const ACCESS_TOKEN = import.meta.env.VITE_MAGENTO_ACCESS_TOKEN;
const PAGE_SIZE = 12;
async function magentoFetch(path) {
const response = await fetch(`${BASE_URL}${path}`, {
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`,
},
});
if (!response.ok) {
throw new Error(`Magento API error: ${response.status}`);
}
return response.json();
}
export async function fetchProducts({ page = 1, sortField = 'name', direction = 'ASC' } = {}) {
const params = new URLSearchParams({
'searchCriteria[pageSize]': PAGE_SIZE,
'searchCriteria[currentPage]': page,
'searchCriteria[sortOrders][0][field]': sortField,
'searchCriteria[sortOrders][0][direction]': direction,
});
const data = await magentoFetch(`/products?${params.toString()}`);
return {
products: data.items,
totalCount: data.total_count,
pageCount: Math.ceil(data.total_count / PAGE_SIZE),
};
}URLSearchParams handles correct URL encoding automatically – considerably less error-prone than manually assembling a string with template literals.
components/Pagination.jsx
function Pagination({ currentPage, pageCount, onPageChange }) {
return (
<div>
<button
onClick={() => onPageChange(currentPage - 1)}
disabled={currentPage <= 1}
>
Previous
</button>
<span>
{' '}Page {currentPage} of {pageCount}{' '}
</span>
<button
onClick={() => onPageChange(currentPage + 1)}
disabled={currentPage >= pageCount}
>
Next
</button>
</div>
);
}
export default Pagination;ProductListPage.jsx: integrating pagination
import { useEffect, useState } from 'react';
import { fetchProducts } from '../api/magentoApi';
import Pagination from '../components/Pagination';
function ProductListPage() {
const [products, setProducts] = useState([]);
const [pageCount, setPageCount] = useState(1);
const [currentPage, setCurrentPage] = useState(1);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
async function load() {
const result = await fetchProducts({ page: currentPage });
setProducts(result.products);
setPageCount(result.pageCount);
setLoading(false);
}
load();
}, [currentPage]);
if (loading) {
return <p>Loading products...</p>;
}
return (
<div>
<h1>Products</h1>
<ul>
{products.map((product) => (
<li key={product.sku}>
{product.name} — {product.price} €
</li>
))}
</ul>
<Pagination
currentPage={currentPage}
pageCount={pageCount}
onPageChange={setCurrentPage}
/>
</div>
);
}
export default ProductListPage;[currentPage] as the useEffect dependency ensures a reload happens automatically on page change – EXACTLY the same pattern as [sku] in "React for Beginners" chapter 22.
Tipp: Test it: if your shop has more than 12 products, "Next"/"Previous" should now ACTUALLY load different products – a good moment to check in your Magento admin whether the displayed order matches sortField: 'name'.