Layout Cache

The Rust LayoutEngine caches Taffy layout results in a 2-slot LRU cache (one for header height, one for row height). Scrolling reuses cached column positions instead of recomputing Taffy layout every frame.

Use engineRef to access invalidateLayout() — forces cache clear so the next frame recomputes from scratch. Changing layout props (flex-direction, gap, etc.) automatically causes a cache miss.

flex-direction:
gap:

Grid API

Cache Log
Click "Benchmark" to compare cached vs uncached performance, or "invalidateLayout()" to manually clear the cache.
How the cache works:
  • 2-slot LRU — one for header height, one for row height (both hit on every frame)
  • Key = hash of all column + container + viewport_width + row_height + line_height
  • Cache hit = skip Taffy tree build + compute_layout entirely
  • Scrolling only changes scroll_top (not a cache key), so layout is always cached during scroll
  • Changing flex-direction or gap = automatic cache miss = fresh Taffy computation

Code

const engineRef = useRef<WasmTableEngine | null>(null);

// Clear layout cache (forces Taffy recomputation on next frame)
engineRef.current?.invalidateLayout();

<Grid data={data} columns={columns} engineRef={engineRef} flexDirection="row" gap={0} />;

Table API Code

import {
  Table,
  useReactTable,
  flexRender,
  getCoreRowModel,
  Thead,
  Tbody,
  Tr,
  Th,
  Td,
  type WasmTableEngine,
} from "@ohah/react-wasm-table";

const engineRef = useRef<WasmTableEngine | null>(null);

// Clear layout cache (forces Taffy recomputation on next frame)
engineRef.current?.invalidateLayout();

const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });

<Table table={table} width={560} height={520} engineRef={engineRef} flexDirection="row" gap={0}>
  <Thead>
    {table.getHeaderGroups().map((hg) => (
      <Tr key={hg.id}>
        {hg.headers.map((h) => (
          <Th key={h.id} colSpan={h.colSpan}>
            {h.isPlaceholder ? null : flexRender(h.column.columnDef.header, h.getContext())}
          </Th>
        ))}
      </Tr>
    ))}
  </Thead>
  <Tbody>
    {table.getRowModel().rows.map((row) => (
      <Tr key={row.id}>
        {row.getVisibleCells().map((cell) => (
          <Td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</Td>
        ))}
      </Tr>
    ))}
  </Tbody>
</Table>;