LyteNyte Grid logo for light mode. Links back to the documentation home page.
Cells

Cell Renderers

Cell renderers are custom React components you assign to a column definition to control what each cell displays. Assign one to a specific column or set it in the base column definition to apply it to every grid cell.

Defining a Cell Renderer

Set the cellRenderer property on a column to provide the column with a component to use when rendering the content of that cell. The cellRenderer property is a React function component that receives a set of props from LyteNyte Grid. These props conform to the Grid.T.CellRendererParams type.

The demo below assigns a custom cell renderer for each column. Click Expand Code to see that each column has its cellRenderer property set. The components.tsx file defines the renderer components.

Custom Cell Renderers

Fork code on stack blitzFork code on code sandbox

Cell renderers are React components. They render within your application’s React tree and can read any existing React context. The Grid.T.CellRendererParams type provides the most common properties for cell rendering. Additional state can be provided by extending the grid’s API or creating a context value for use in the cell.

The following code implements the cell renderer for the Product column. LyteNyte Grid uses standard React components, so you don’t need specialized grid APIs or patterns. You can leverage your existing React expertise without learning a proprietary API.

export function ProductCell({ api, row }: Grid.T.CellRendererParams<GridSpec>) {
if (!api.rowIsLeaf(row) || !row.data) return;
const url = row.data?.productThumbnail;
const title = row.data.product;
const desc = row.data.productDescription;
return (
<div className="flex h-full w-full items-center gap-2">
<img className="border-ln-border-strong h-7 w-7 rounded-lg border" src={url} alt={title + desc} />
<div className="text-ln-text-dark flex flex-col gap-0.5">
<div className="font-semibold">{title}</div>
<div className="text-ln-text-light text-xs">{desc}</div>
</div>
</div>
);
}

Column Field

Each cell derives its value from the column’s field property. The grid handles data retrieval differently for leaf rows than for group or aggregated rows. When you define field as a function or path, the grid resolves the value dynamically rather than accessing the row data via a direct key.

To simplify value retrieval, columnField returns the cell value for a specific row. In the demo below, the Balance column’s cell renderer calls columnField to retrieve the cell value.

Cell Value

Fork code on stack blitzFork code on code sandbox

By calling api.columnField to retrieve the cell value, the renderer avoids branching on row type. See the code below.

export function NumberCell({ api, row, column }: Grid.T.CellRendererParams<GridSpec>) {
const field = api.columnField(column, row);
if (typeof field !== "number") return "-";
const formatted = field < 0 ? `-$${formatter.format(Math.abs(field))}` : "$" + formatter.format(field);
return (
<div
className={tw(
"flex h-full w-full items-center justify-end tabular-nums",
field < 0 && "text-red-600 dark:text-red-300",
field > 0 && "text-green-600 dark:text-green-300",
)}
>
{formatted}
</div>
);
}

Cell State and Virtualization

LyteNyte Grid uses virtualization by default. As you scroll, React unmounts off-screen rows and remounts them as they re-enter the viewport, resetting any local state.

To persist client state across scrolls, lift that state above the cell renderer in the React tree. Use a parent component or a context provider rather than useState inside the renderer.

function MyGrid() {
return (
<MyStateProvider>
<Grid />
</MyStateProvider>
);
}
function MyCustomCell() {
// Using `useState` will result in temporary state when virtualization is on.
// const [localState, setLocalState] = useState()
const resilientCellState = useMyStateProvider();
// My cell renderer
}

Optimizing Cell Renderers

LyteNyte Grid supports any cell renderer content. Follow these guidelines to maximize performance and usability:

  • Keep Renderers Lightweight: Avoid expensive computations in the render path because they degrade scroll performance. The grid can render thousands of cells per update. Memoize complex calculations where possible.
  • Derive State From Props: Use Grid.T.CellRendererParams to access row state. For example, use the selected property to render selection feedback rather than tracking state locally.
  • Respect Cell Boundaries: Cells clip overflow by default. Ensure content fits within defined dimensions to avoid truncation.

Next Steps