Make interactive node-based graphs with React Flow. 📈
Tags: react, tutorial, javascript, webdev
Published: 2020-06-05 14:04:06

Recently I was browsing some React libraries I need to work on. My criteria for selection was to find new and not so many famous ones but they should also be useful for scalable projects. I hunted various categories from app state management to real-time web sockets. While those were useful and were used by thousands of developers, there was this one which was someone hidden under some big names.

This is [React Flow](https://github.com/wbkd/react-flow), and as described in their repo:

> React Flow is a library for building node-based graphs. You can easily implement custom node types and it comes with components like a mini-map and graph controls.

I chose this because I think it's useful to make interactive graphs uniquely and yes, it's quite easy to get started! So, let's make something, let's make a cool node-based graph with React Flow. 😎 

---

## Well, first some features 😋

Here are the top features or reasons why you should use React Flow library in your React app:

1. **Easy to integrate and work on**: It wouldn't take you more than 5 mins to see your first graph live in the app. That's what I call 'easy'!

2. **Comes with extra plugins**: You want a minimap just like you see in Sublime Text or you may want to add controls to your graph with panning/zooming? Say no more. The support is great and can be done with less code.

3. **Customizable**: The entire library can be worked on multiple nodes, interactivities, and styles.

## Let's start! 👨‍💻

![Ring Ring](https://media.giphy.com/media/7zizfFtXJBOeyfsgOh/giphy.gif)
<figcaption>Ring ring!</figcaption> 


#### 1. Installation:
Just grab your old friend NPM and run the following command (of course after you're done creating a React app):

```
npm install react-flow-renderer
```
Make sure it's installed correctly by going to your _package.json_ file and looking for `react-flow-renderer` as a dependency.

#### 2. Creating our first graph:
We need to clear out a few terms first. Here are some:

- _Elements_: It's an object which is like a container of all the 'nodes' and the 'edges'.

- _Nodes_: These are the individual _boxes_ which may contain some text or information.

- _Edges_: This is like a connector between two nodes. If you want the graph to show a connection between two or more nodes, you create edges. These can be characterised by the presence of a `source` and a `target` attribute. 

- _Node types_: There are three of them available. The first, 'input 🟪' which can also be the source node. Second is the 'default 🟧' similar to the default node you get and the third one is the 'output 🟩' that can be used to show the result of a process. As we know the library is highly customisable so we can create our node type as a 'custom 🟨' one.

- _Edge types_: Similar to node types you get a 'straight', 'default' and a 'step' type. You can even go ahead and have a [custom edge type](https://github.com/wbkd/react-flow/blob/master/example/src/CustomNode/index.js)!

- _Graph control plugin_: A very handy plugin to add features like zoom-in, zoom-out and focus on the graph.

![Graph control](https://webkid.io/content/images/2020/reactflow-controls.png)

- _Mini map plugin_: If you have a complex or a large graph, this will show you a map of the entire diagram on a small box from where you get the overview. 

![Mini map](https://webkid.io/content/images/2020/reactflow-minimap.png)

Okay, enough, I'll use these terms from now on.

To make a new graph we need to add elements, some styling and render them. First, make the `elements` object containing the necessary data for your nodes. 

```js
const elements = [
  { id: "1", data: { label: "Parent" }, position: { x: 500, y: 150 } },
  { id: "2", data: { label: "First child" }, position: { x: 400, y: 250 } },
  { id: "e1-2", source: "1", target: "2", animated: true }
];
```
We make 2 nodes here with unique `id` value, some `label`s and default positions with respective `x` and `y` coordinate values. The third object is the edge that connected the `source` node with `id` 1 to `target` node. Also, for that fancy dotted animation, we set the boolean value to `true`.

Next, we need to add basic styles to our nodes. This is required to render or else, you'll be greeted with the following error:

_"The React Flow parent container needs a width and a height to render the graph."_

Something you don't want to mess with (which I did because I thought styles aren't necessary! Meh...)

```js
const graphStyles = { width: "100%", height: "500px" };
```
We simply provide what it said in the error. A default value of `width` and `height`.

Next, we make the `BasicGraph` function which needs `elements` and `style` attributes inside the `<ReactFlow />` component.

```js
const BasicGraph = () => <ReactFlow elements={elements} style={graphStyles} />;
```
Let's render it by passing the <BasicGraph /> component inside our `return`:

```js
export default function App() {
  return <BasicGraph />;
}
```

![Panning and dragging node demo](https://dev-to-uploads.s3.amazonaws.com/i/eli1eq570dqrajfmv9ll.gif)
<figcaption>Save it and boom! You made your first graph in a few minutes. How easy!</figcaption>

#### 3. Create a custom node:
For this, we make a new element object called `customElement` but this time, let's add styles inside this one because we need a custom `style`, `data` and the starting `position`.

```js
const customElement = [
  {
    id: "1",
    style: {
      background: "#454052",
      width: 200,
      color: "#fff",
      fontSize: "20px",
      fontFamily: "Helvetica",
      boxShadow: "5px 5px 5px 0px rgba(0,0,0,.10)"
    },
    data: { label: "My custom node" },
    position: { x: 500, y: 250 }
  },
  {
    id: "2",
    style: {
      background: "#fff",
      width: 400,
      color: "#454052",
      fontSize: "25px",
      fontFamily: "Helvetica",
      boxShadow: "5px 5px 5px 0px rgba(0,0,0,.10)"
    },
    data: { label: "My second custom node 😉" },
    position: { x: 550, y: 300 }
  }
];
```
See how we have different `id` values, use custom `style` just like the CSS-in-JS concept and have a `label`. Most of this is self-explanatory as this is really simple to use and implement.

![Custom node demo](https://dev-to-uploads.s3.amazonaws.com/i/22wvex32tprdt59x3ols.jpg)
<figcaption>This is what we get after making two custom nodes.</figcaption>

#### 4. Experiment with edge styles:
Let's hop on to edges! Here, we change the `elements` object we made earlier for nodes as per our requirement. Here, I've made quite a complex one:

```js
const elements = [
  {
    id: "1",
    type: "input",
    data: { label: "Master Node" },
    position: { x: 50, y: 50 }
  },
  { id: "2", data: { label: "Node 2" }, position: { x: 100, y: 100 } },
  { id: "3", data: { label: "Node 3" }, position: { x: 250, y: 150 } },
  { id: "4", data: { label: "Node 4" }, position: { x: 500, y: 200 } },
  { id: "5", data: { label: "Node 5" }, position: { x: 750, y: 250 } },
  {
    id: "6",
    data: { label: "Node 6" },
    position: { x: 800, y: 300 },
    type: "output"
  },
  { id: "e1-2", source: "3", target: "2", type: "straight" },
  { id: "e1-3", source: "1", target: "3", type: "default" },
  { id: "e1-4", source: "1", target: "4", type: "default" },
  { id: "e1-5", source: "5", target: "2", type: "step", animated: true },
  { id: "e1-6", source: "1", target: "6", type: "step" }
];
```
It's not as confusing as it may seem. We've simply created a master node with `id` of 1. Notice how I made its type as `input`. Node number 2, 3, 4 and 5 are just normal children. As for the 6th one, we made it an `output` type.

For connections between the edges, we use the typical `source` - `target` pair of attributes. One good thing to note is the different lines you get, that comes from the `type` of the edge.

![Multi node demo](https://dev-to-uploads.s3.amazonaws.com/i/k5ipvd7mvn2wd6le141x.gif)

Bonus! If you need to make your node or edge type, look at [this example](https://github.com/wbkd/react-flow/blob/master/example/src/CustomNode/index.js).

Here's the entire Sandbox of the above example:

{% codesandbox react-flow-demo-h2kl5 %}

---