Skip to content

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:

tsx
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.

tsx
const focusedCell = selectFocusedCell(state);
// { rowId: string, colId: string } | null

selectFocusMode

Returns the current focus mode.

tsx
const mode = selectFocusMode(state);
// 'navigation' | 'edit' | 'interactive'

selectIsEditing

Returns whether the grid is in edit mode.

tsx
const isEditing = selectIsEditing(state);
// boolean

selectEditingCell

Returns the cell being edited, or null.

tsx
const editingCell = selectEditingCell(state);
// { rowId: string, colId: string } | null

Selection Selectors

selectSelectionRanges

Returns all selection ranges.

tsx
const ranges = selectSelectionRanges(state);
// Array<{ start: CellRef, end: CellRef }>

selectIsSelected

Returns whether a specific cell is in the selection.

tsx
const isSelected = selectIsSelected(state, { rowId, colId });
// boolean

selectSelectionBounds

Returns the bounding box of the selection.

tsx
const bounds = selectSelectionBounds(state);
// { startRow: number, endRow: number, startCol: number, endCol: number } | null

selectSelectedCells

Returns all selected cell references.

tsx
const cells = selectSelectedCells(state);
// Array<{ rowId: string, colId: string }>

Derived Selectors

selectIsCellFocused

Checks if a specific cell is focused.

tsx
const isFocused = selectIsCellFocused(state, { rowId, colId });
// boolean

selectIsCellEditing

Checks if a specific cell is being edited.

tsx
const isEditing = selectIsCellEditing(state, { rowId, colId });
// boolean

selectRowHasSelection

Checks if any cell in a row is selected.

tsx
const hasSelection = selectRowHasSelection(state, rowId);
// boolean

Performance Tips

Use Shallow Equality

For selectors that return objects or arrays, use Zustand's shallow comparator:

tsx
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:

tsx
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:

tsx
// 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

Released under the MIT License.