-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture useGridVisibleRows
📝 Generated from
docs/architecture/use-grid-visible-rows.md. Edit it there; changes made in the wiki are overwritten.
Internal hook. Merges the pinned top rows, the virtual center window, and the pinned bottom rows into a single { row, rowIndex }[] array — exactly what the viewport JSX iterates to render <Row> components.
File: lib/hooks/core/useGridVisibleRows.ts
The render window is the intersection of what the row pipeline produced and what the virtualization engine says is visible. Before this hook, ~40 lines of useMemo logic lived inline in DataGrid.tsx. Extracting it makes the merge strategy explicit and independently testable.
interface UseGridVisibleRowsParams<R extends GridRowModel> {
renderContext: {
firstRowIndex: number; // from useGridVirtualization
lastRowIndex: number;
};
pinnedTopRows: R[]; // from useGridRowPipeline
pinnedBottomRows: R[]; // from useGridRowPipeline
paginatedUnpinnedRows: R[]; // from useGridRowPipeline
sortedUnpinnedRows: R[]; // from useGridRowPipeline
pagination: boolean;
}GridVisibleRow<R>[]
// where GridVisibleRow<R> = { row: R; rowIndex: number }rowIndex is the position in the renderable rows (top-pinned + the current page's centre rows + bottom-pinned) — it becomes the row's data-rowindex, the rowIndex in onRowClick / getDetailPanelContent params and the zebra-stripe class. aria-rowindex is computed separately (lib/utils/aria, getAriaRowLayout): it adds the header rows and, for centre rows, the rows on earlier pages, and puts bottom-pinned rows after every page. GridPinnedRows receives the bottom rows' offset (topPinned + centerCount) so they no longer restart at 0.
topPinned: rows 0 .. pinnedTopRows.length - 1 (always fully rendered)
center: rows [firstRowIndex - topPinnedCount, lastRowIndex - topPinnedCount]
(clipped to the virtual window)
bottomPinned: rows (topPinned + centerCount) .. end (always fully rendered)
Pinned rows are NOT subject to virtualization — they are always in the DOM regardless of scroll position.
After merging, the hook filters out any row whose id has already been seen:
const seenIds = new Set<GridRowId>();
return combined.filter(item => {
if (seenIds.has(item.row.id)) return false;
seenIds.add(item.row.id);
return true;
});Why: If a user passes the same row in both rows and pinnedRows, it would appear in both pinnedTopRows and paginatedUnpinnedRows. Two <Row key={id}> elements with the same key cause React reconciliation bugs. The guard ensures each ID appears at most once — the pinned version takes precedence since it comes first in the merged array.
Entries from the pinned sections carry pinned: 'top' | 'bottom'. GridVirtualRows renders only the untagged (center) entries, in one linear pass; it does not de-duplicate again and does not consult the raw pinnedRows prop, so under tree data / row grouping (where nothing is pinned) every row still renders in its place.
DataGrid.tsx calls this hook after useGridVirtualization produces the render context and after useGridRowPipeline produces the pinned/paginated row groups. The returned visibleRows array is iterated directly in the viewport JSX.
OpenGridX 3.2.2 · MIT · This wiki is generated from docs/ on every push to main. To fix a page, open a PR against the source file.
Start here
Components
- DataGrid
- Header
- Row
- Cell
- Toolbar
- Pagination
- Filter Panel
- Tooltip
- Column Visibility
- Column Grouping
- Column Resizing
- Empty State
- Error Overlay
- Aggregation Footer
Features
- Virtualization
- Filtering & Search
- Sorting & Pagination
- Custom Pagination
- Editing & Reordering
- Row Selection
- Clipboard
- Pinning
- State Persistence
- Aggregation & Pivot
- Tree Data & Grouping
- Cell Spanning
- Master-Detail
- Keyboard & Accessibility
- List View
- Infinite Scroll
- Data Source
- Loading States
- Toolbar Customization
- Export (CSV, Excel, JSON, Print)
- PDF Export
Customization
Upgrading
Contributing
- Contributing
- Testing
- Roadmap
- DataGrid orchestration
- GridRowMeta
- useGridControlledState
- useGridRowPipeline
- useGridColumns
- useGridVirtualization
- useGridVisibleRows
- useGridScrollSync
- useGridStateSnapshot