javascript
41 lines · 8 steps
Building and parsing pagination URLs
A round-trip pair of functions that serialize list state into a query string and read it back out safely.
Explained by
highlit
1export function buildPaginationUrl(baseUrl, { page, perPage, filters = {}, sort } = {}) {
2 const url = new URL(baseUrl);
3 const params = url.searchParams;
4
5 if (page != null) params.set('page', String(page));
6 if (perPage != null) params.set('per_page', String(perPage));
7 if (sort) params.set('sort', sort);
8
9 for (const [key, value] of Object.entries(filters)) {
10 params.delete(key);
11 if (Array.isArray(value)) {
12 for (const item of value) params.append(key, item);
13 } else if (value != null && value !== '') {
14 params.set(key, String(value));
15 }
16 }
17
18 params.sort();
19 return url.toString();
20}
21
22export function parseListParams(queryString) {
23 const params = new URLSearchParams(queryString);
24 const page = Number.parseInt(params.get('page') ?? '1', 10);
25 const perPage = Number.parseInt(params.get('per_page') ?? '25', 10);
26
27 const reserved = new Set(['page', 'per_page', 'sort']);
28 const filters = {};
29 for (const key of new Set(params.keys())) {
30 if (reserved.has(key)) continue;
31 const values = params.getAll(key);
32 filters[key] = values.length > 1 ? values : values[0];
33 }
34
35 return {
36 page: Number.isNaN(page) ? 1 : Math.max(page, 1),
37 perPage: Number.isNaN(perPage) ? 25 : Math.min(perPage, 100),
38 sort: params.get('sort'),
39 filters,
40 };
41}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1The URL and URLSearchParams APIs handle escaping and multi-value keys so you never hand-concatenate query strings.
- 2Sorting params before stringifying makes otherwise-equivalent URLs byte-identical, which is friendly to caches.
- 3Parsing untrusted input should always clamp and default values rather than trust whatever arrived.
Related explainers
java
public record AppConfig( String host, int port, String databaseUrl,
Loading typed config from env vars in Java
records
configuration
environment-variables
Intermediate
6 steps
php
<?php namespace App\Validation;
Building a reusable address form validator in PHP
validation
error-accumulation
regex
Intermediate
9 steps
javascript
const { Pool } = require('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL,
Per-request Postgres connections in Express
connection-pooling
middleware
transactions
Intermediate
8 steps
php
<?php namespace App\Http\Controllers;
A cached autocomplete endpoint in Laravel
caching
validation
query-ranking
Intermediate
8 steps
javascript
const express = require('express'); const router = express.Router(); const db = require('../db');
Building a paginated orders page in Express
pagination
routing
sql-queries
Intermediate
7 steps
javascript
import { Suspense } from 'react'; import { searchProducts } from '@/lib/products'; import SearchInput from './search-input';
Streaming search results in a Next.js Server Component
server-components
suspense
streaming
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/building-and-parsing-pagination-urls-explained-javascript-b8f1/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.