Skip to main content

Pagination

Pagination is the page-navigation control for long result sets.

Use it when the product already has a concept of discrete pages, such as search results, logs, invoices, or admin tables. Pagination solves a different problem than infinite scroll. It trades continuous browsing for clear location, predictable back-and-forth movement, and stable URLs or queries.

Example

use fission::prelude::*;
use std::sync::Arc;

let node = Pagination {
current_page: view.state.page,
total_pages: view.state.total_pages,
on_change: Some(Arc::new(move |page| ActionEnvelope {
id: set_page_id,
payload: serde_json::to_vec(&SetPage(page)).unwrap(),
})),
}
.build(ctx, view);

The reducer usually stores the current page and then refreshes the data set through a selector or follow-up effect.

Field table

FieldTypeMeaningNotes / default behavior
current_pageusizeCurrently selected page number.The checked-in widget behaves as a 1-based pager.
total_pagesusizeTotal number of available pages.Provide a value of at least 1 for normal use.
on_changeOption<Arc<dyn Fn(usize) -> ActionEnvelope + Send + Sync>>Closure that builds the action for a chosen page.Called for previous, next, and numbered page buttons.

State ownership and behavior

The widget does not calculate paging for you. It only renders page controls from the current state. The reducer still decides what page data to load and how page numbers map to queries or offsets.

The checked-in implementation shows a sliding window of page buttons with ellipses when needed. Previous and next buttons disable themselves at the ends of the range.

Specific advice

Use pagination only if the product already benefits from discrete pages. If users mostly scan continuously through a stream, pagination can feel like unnecessary friction.

DataTable, Scroll, LazyColumn, and EmptyState.