# React quick start

Render a typed, editable diagram in React, size its canvas, keep the graph in React state, and retain the mounted instance for imperative calls.

## The idea

[`GrafloriaFlow`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-react#grafloriaflow) renders node and edge data as an editable React canvas. The shared engine handles dragging, connecting, panning, and zooming.

## Prerequisites and installation

Use React 17, 18, or 19 with the matching `react-dom` version. Install the React binding and its peer packages:

```bash
npm install @grafloria/react @grafloria/engine @grafloria/renderer react react-dom @grafloria/element
```

## Build the diagram

1. Create `App.tsx` with typed node and edge arrays. [`NodeSpec`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-renderer-instance-nodespec#nodespec) describes each box, and [`EdgeSpec`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-renderer-instance-edgespec#edgespec) connects node IDs.

2. Give the flow a real width and height through `style`. The component's canvas uses the host's resolved size; a host with no height renders no visible canvas.

3. Use [`useNodesState`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-react#usenodesstate) and [`useEdgesState`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-react#useedgesstate) for controlled state. Pass the third value from each tuple back to the corresponding change prop. This lets a drag update React state instead of snapping the node back to the previous render.

4. Capture the [`DiagramInstance`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-renderer-instance-diagraminstance#diagraminstance) in `onInit`. The button below calls `fitView()` on the mounted instance, framing the two nodes without rebuilding the component.

```tsx title="App.tsx"
import { useRef } from 'react';
import {
  GrafloriaFlow,
  useEdgesState,
  useNodesState,
} from '@grafloria/react';
import type {
  DiagramInstance,
  EdgeSpec,
  NodeSpec,
} from '@grafloria/react';

const initialNodes: NodeSpec[] = [
  {
    id: 'ingest',
    position: { x: 60, y: 80 },
    size: { width: 180, height: 80 },
    data: { label: 'Ingest' },
  },
  {
    id: 'publish',
    position: { x: 380, y: 80 },
    size: { width: 180, height: 80 },
    data: { label: 'Publish' },
  },
];

const initialEdges: EdgeSpec[] = [
  { id: 'ingest-to-publish', source: 'ingest', target: 'publish' },
];

export default function App() {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, , onEdgesChange] = useEdgesState(initialEdges);
  const instanceRef = useRef<DiagramInstance | null>(null);

  function addNode() {
    setNodes((current) => [
      ...current,
      {
        id: `node-${current.length}`,
        position: { x: 220, y: 240 },
        size: { width: 180, height: 80 },
        data: { label: 'New step' },
      },
    ]);
  }

  return (
    <main>
      <button type="button" onClick={addNode}>
        Add node
      </button>
      <button
        type="button"
        onClick={() => instanceRef.current?.fitView()}
      >
        Fit view
      </button>
      <GrafloriaFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onInit={(instance) => {
          instanceRef.current = instance;
        }}
        plugins
        style={{ width: '100%', height: 480 }}
      />
    </main>
  );
}
```

![The browser result of the mounted React flow.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/b0c9167e4e826f3330f14d04febd43ca.png)

The mounted result shows two labelled boxes joined by an edge in a 480-pixel-tall canvas. You can drag either box, pan, zoom, and draw connections. `plugins` adds the canvas controls, minimap, and background. Selecting **Fit view** calls the captured instance and frames the current content.

For a self-contained viewer or demo, use `defaultNodes` and `defaultEdges` instead. Those props seed the instance, which owns the data afterward; use controlled `nodes` and `edges` when another part of your application needs to persist or inspect the graph.

## Where next

- [Style a diagram](https://atloria.dev/p/grafloria-h7YM7amryF/developer/style-a-diagram) explains container sizing and presentation options.
- [State and data flow in React](https://atloria.dev/p/grafloria-h7YM7amryF/developer/instance-and-bindings) covers controlled versus uncontrolled ownership in more depth.
- [Commands, events, and undo](https://atloria.dev/p/grafloria-h7YM7amryF/developer/commands-events-and-undo) shows how to reach engine behavior through the instance.
- Try the [React starter](https://grafloria.com/react/) or inspect its [source](https://github.com/grafloria/grafloria/blob/ef2bcc55237d4d1f1643b6fea68bd996aa37a9e9/starters/react).
