Implementing Page-Size Validation
To prevent silent failures or performance degradation caused by invalid pagination parameters, you should implement a clamping mechanism within your selector. In NgRx, selectors must remain pure functions; therefore, throwing a TypeError is discouraged as it would crash the selector chain and potentially the entire application UI.
Recommended Implementation
The most robust approach is to automatically clamp the pageSize to a safe range (e.g., between 1 and a defined maximum) before the slicing operation occurs. This ensures the selector always returns a valid array without triggering side effects.
import { createSelector } from '@ngrx/store';
const MIN_PAGE_SIZE = 1;
const MAX_PAGE_SIZE = 100;
export const selectPaginatedEntities = createSelector(
selectEntityArray, // The full list of entities
selectPaginationState, // { pageIndex: number, pageSize: number }
(entities, pagination) => {
// Validate and clamp the page size
const safePageSize = Math.max(
MIN_PAGE_SIZE,
Math.min(MAX_PAGE_SIZE, pagination.pageSize)
);
const start = pagination.pageIndex * safePageSize;
return entities.slice(start, start + safePageSize);
}
);
Analysis of Validation Strategies
| Strategy |
Behavior |
Verdict |
| Throw TypeError |
Crashes the selector chain on invalid input. |
Avoid: Too disruptive for UI state. |
| Automatic Clamping |
Resets $\le 0$ to 1 and caps excessively large values. |
Recommended: Safe, predictable, and pure. |
| External Validator |
Validates in the component/effect before updating state. |
Supplementary: Good for UX, but doesn't protect the selector. |
Verification Steps
- Negative/Zero Test: Dispatch an action setting
pageSize to 0 or -1. Verify the selector returns a slice of 1 element (or the MIN_PAGE_SIZE).
- Overflow Test: Set
pageSize to 10,000. Verify the selector caps the result at MAX_PAGE_SIZE.
- State Integrity: Check Redux DevTools to confirm that the state still holds the "invalid" number, while the selector output is corrected. This decouples the raw state from the view logic.
Diagnostic Note: Are you currently calculating the pageIndex based on a total count in the selector, or is the index managed independently in the state? If the index is managed independently, you may also need to clamp the start offset to prevent it from exceeding the total array length.