Lattice Grid Buy a licence

demo D06

Loading data after the grid exists in React

An empty grid that fills from a fetch, with the loading state between

rows.load(data)

This grid is created empty and then filled from a fetch, showing the loading state in between. It matches how most apps really work, the shell renders first and the rows arrive a moment later, so you can build the grid before the data exists and drop it in when it lands.

Building…
Loading a live grid…

This is the React version. The grid mounts through the createLatticeGrid adapter, which takes its configuration as ordinary props and hands back the live grid through a ref. The grid below is the same one every other tab runs.

The configuration

<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">

<div id="grid"></div>

<script type="module">
  import React from 'https://esm.sh/react@18';
  import { createRoot } from 'https://esm.sh/react-dom@18/client';
  import { createGrid } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.esm.min.js';
  import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/react.esm.min.js';

  const LatticeGrid = createLatticeGrid({ React, createGrid });

  const columns = [
    { field: 'circuit', title: 'Circuit', layout: { width: 180 } },
    { field: 'region', title: 'Region' },
    { field: 'status', title: 'Status', filter: { type: 'set' } },
    { field: 'bandwidth', title: 'Bandwidth', type: 'number' },
    { field: 'charge', title: 'Monthly charge', type: 'number',
      format: { style: 'currency', currency: 'GBP' } },
  ];

  function App() {
    const gridRef = React.useRef(null);

    // Mount empty, then hand the grid its rows once the fetch resolves. The
    // empty state shows until rows.load() is called, and the grid repaints in
    // place after, with no rebuild.
    React.useEffect(() => {
      let live = true;
      fetch('/api/circuits')
        .then((r) => r.json())
        .then((rows) => { if (live) gridRef.current.grid.rows.load(rows); });
      return () => { live = false; };
    }, []);

    return (
      <LatticeGrid
        ref={gridRef}
        rowKey="id"
        columns={columns}
        rows={[]}
        style={{ height: '540px' }}
      />
    );
  }

  createRoot(document.getElementById('grid')).render(<App />);
</script>

Populating a grid after it mounts

Most integrations construct the grid before the data exists: a dashboard shell renders, an API call goes out, and the rows arrive some milliseconds later. Lattice Grid separates these two moments deliberately. createGrid builds the columns, the header and the empty body immediately, and rows.load(data) fills it whenever the fetch resolves, without a second construction step or a full remount. This is the shape a JavaScript data grid needs for any screen backed by a remote call, a websocket handshake, or a route that streams from a loader before its data dependency settles.

Between construction and the load call, the grid shows a loading state rather than an empty table with no explanation, so the viewer sees a grid that is working rather than one that has failed to render. Once rows.load runs, the body populates in place: scroll position, column widths and any sort or filter already configured on the grid all carry over, because the grid was never torn down to receive its data.

The same call handles a refresh, not only the first load. Calling rows.load again replaces the row set cleanly, which makes it the entry point for both the initial fetch and any subsequent reload triggered by the host application.

How do you show a loading state before a data grid has data?

Construct the grid immediately with createGrid(el, { columns, rows: [] }), so the header and empty body render before the fetch completes. Lattice Grid displays a built-in loading state for the empty body automatically; when the request resolves, call rows.load(data) to fill it, and the same call works again for any later refresh.