Selectors
Functions for subscribing to specific slices of grid state. Use selectors to minimize re-renders.
Overview
Selectors extract specific data from the grid state. Combined with Zustand's useStore, they enable granular subscriptions:
import { useStore } from "zustand";
import { selectFocusedCell, selectIsSelected } from "@ts-zen/react-datagrid";
function Cell({ grid, rowId, colId }) {
// Only re-renders when this specific cell's focus state changes
const isFocused = useStore(
grid.store,
(state) =>
selectFocusedCell(state)?.rowId === rowId && selectFocusedCell(state)?.colId === colId,
);
// Only re-renders when this cell's selection state changes
const isSelected = useStore(grid.store, (state) => selectIsSelected(state, { rowId, colId }));
}Focus Selectors
selectFocusedCell
Returns the currently focused cell reference, or null.
const focusedCell = selectFocusedCell(state);
// { rowId: string, colId: string } | nullselectFocusMode
Returns the current focus mode.
const mode = selectFocusMode(state);
// 'navigation' | 'edit' | 'interactive'selectIsEditing
Returns whether the grid is in edit mode.
const isEditing = selectIsEditing(state);
// booleanselectEditingCell
Returns the cell being edited, or null.
const editingCell = selectEditingCell(state);
// { rowId: string, colId: string } | nullSelection Selectors
selectSelectionRanges
Returns all selection ranges.
const ranges = selectSelectionRanges(state);
// Array<{ start: CellRef, end: CellRef }>selectIsSelected
Returns whether a specific cell is in the selection.
const isSelected = selectIsSelected(state, { rowId, colId });
// booleanselectSelectionBounds
Returns the bounding box of the selection.
const bounds = selectSelectionBounds(state);
// { startRow: number, endRow: number, startCol: number, endCol: number } | nullselectSelectedCells
Returns all selected cell references.
const cells = selectSelectedCells(state);
// Array<{ rowId: string, colId: string }>Derived Selectors
selectIsCellFocused
Checks if a specific cell is focused.
const isFocused = selectIsCellFocused(state, { rowId, colId });
// booleanselectIsCellEditing
Checks if a specific cell is being edited.
const isEditing = selectIsCellEditing(state, { rowId, colId });
// booleanselectRowHasSelection
Checks if any cell in a row is selected.
const hasSelection = selectRowHasSelection(state, rowId);
// booleanPerformance Tips
Use Shallow Equality
For selectors that return objects or arrays, use Zustand's shallow comparator:
import { shallow } from "zustand/shallow";
const { isFocused, isSelected } = useStore(
grid.store,
(state) => ({
isFocused: selectIsCellFocused(state, cellRef),
isSelected: selectIsSelected(state, cellRef),
}),
shallow,
);Memoize Selector Results
For computed values, memoize at the component level:
const cellState = useStore(
grid.store,
(state) => ({
focused: selectIsCellFocused(state, cellRef),
selected: selectIsSelected(state, cellRef),
editing: selectIsCellEditing(state, cellRef),
}),
shallow,
);
// Derive styles once per render
const className = useMemo(
() =>
cn(
cellState.focused && "ring-2",
cellState.selected && "bg-blue-50",
cellState.editing && "bg-white",
),
[cellState],
);Avoid Inline Selectors
Create stable selector references:
// Bad: new function every render
useStore(grid.store, (state) => selectIsSelected(state, { rowId, colId }));
// Good: stable reference
const selector = useCallback((state) => selectIsSelected(state, { rowId, colId }), [rowId, colId]);
useStore(grid.store, selector);See Also
- Hooks — Higher-level API with built-in selectors
- State Model — Understanding the state structure