Open Source
webkid
May 05, 2020

React Flow - A Library for Rendering Interactive Graphs

Moritz Klack
@moklick
Example usage of our new react library
We just open sourced "React Flow": A library for rendering interactive node-based graphs with a smooth panning and zooming behaviour and lots of nice features and even some useful plugins like a mini map!
In this post I will show you a simple example of a React Flow application. If you want to start even faster you can directly go to the documentation or check out the demo:
If we can help you to develop a custom node-based tool we are happy to hear from you: info@webkid.io.
We updated the article to represent the current default styles

Key Features

React Flow not only renders a graph but also adds interactivity and comes with a lot of built-in features:
  • Easy to use: Seamless zooming & panning behaviour and single and multi-selections of elements
  • Customizable: Different node and edge types and support for custom nodes and edges
  • Fast rendering: only elements that are in the view port are displayed
  • Utils: Configurable snap-to-grid behaviour, background styles and graph helper functions
  • Plugin system: Mini map and graph controls
  • Reliable: Written in Typescript and tested with cypress
In order to make this library as flexible as possible we don't do any state updates besides the positions. This means that you need to pass all functions that change the displayed nodes and edges by yourself. You can implement your own ones or use the helper functions that come with the library.

Getting started

You can install React Flow via npm. Unfortunately react-flow was already taken so you need to install react-flow-renderer:
npm install react-flow-renderer
You can now integrate it in your React application. A simple graph could like like this:
import React from 'react';
import ReactFlow from 'react-flow-renderer';
const elements = [
{ id: '1', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
{ id: 'e1-2', source: '1', target: '2', animated: true },
];
const flowStyles = { height: 500 };
const BasicFlow = () => <ReactFlow elements={elements} style={flowStyles} />;
As you can see we are passing elements to the ReactFlow component. In the list of elements there are two nodes and an edge that connects the nodes with each other. You can identify the edge by the presence of a source and target attribute. The nodes have some initial positions so that they don't overlap. We are also passing a style in order to get some space for rendering the graph. You can find a full list of options in the documenation. The example above would like this:
reactflow basic

Node and Edge Types

A graph almost always has different node types. React Flow comes with three basic types: input, default and output. You can select the type by using the type attribute of a node:
const elements = [
{
id: '1',
type: 'input',
data: { label: 'Input node' },
position: { x: 100, y: 5 },
},
{
id: '2',
type: 'default',
data: { label: 'Default node' },
position: { x: 100, y: 100 },
},
{
id: '3',
type: 'output',
data: { label: 'Output node' },
position: { x: 100, y: 200 },
},
];
The different node types look like this:
reactflow node types
As you can see the handles which allows you to connect nodes and the color of the types are different. You can customize these existing types by passing a label and also a style object with css rules:
const elements = [
{
id: '1',
style: { background: '#ffcc50', width: 100 },
data: { label: 'custom style' },
position: { x: 100, y: 5 },
},
];
This would look like this:
reactflow customnode
React Flow has the following edge types: straight, default, step and smoothstep. As with the nodes you can select the type by passing it to an edge in the elements list:
const elements = [
{
id: '1',
type: 'input',
data: { label: 'Node 1' },
position: { x: 5, y: 5 },
},
{ id: '2', data: { label: 'straight' }, position: { x: 100, y: 100 } },
{ id: '3', data: { label: 'default' }, position: { x: 250, y: 150 } },
{ id: '4', data: { label: 'step' }, position: { x: 500, y: 200 } },
{ id: '5', data: { label: 'smoothstep' }, position: { x: 500, y: 200 } },
{ id: 'e1-2', source: '1', target: '2', type: 'straight' },
{ id: 'e1-3', source: '1', target: '3', type: 'default' },
{ id: 'e1-4', source: '1', target: '4', type: 'step' },
{ id: 'e1-5', source: '1', target: '5', type: 'smoothstep' },
];
These are the available edge types:
reactflow edgetypes
If you want like to create a custom node or edge type you can check out the custom node example. There we implement a custom node component and make it available within the renderer by passing it to the React Flow component as a nodeTypes property.

Interactivity

As I pointed out earlier React Flow comes with some basic interactivity but doesn't do state updates for the rendered elements. You can zoom and pan and drag or select elements but if you want to add or remove a node for example you need to implement the function by yourself or use one of the React Flow helper functions. Whenever the elements property change on the React Flow component we re-render the graph. So if you want to add a node for example you need to push a new node to your elements array and pass it to the React Flow component. If you want to remove a node you need to listen to the remove event by passing a function to onElementsRemove prop:
import React, { useState } from 'react';
import ReactFlow, { removeElements } from 'react-flow-renderer';
const initialElements = [
{
id: '1',
type: 'input',
data: { label: 'Node 1' },
position: { x: 5, y: 5 },
},
];
const flowStyles = { height: 300 };
const Flow = () => {
const [elements, setElements] = useState(initialElements);
const onElementsRemove = (elementsToRemove) =>
setElements((els) => removeElements(elementsToRemove, els));
return (
<ReactFlow
elements={elements}
style={flowStyles}
onElementsRemove={onElementsRemove}
/>
);
};

Plugins

React Flow comes with several plugins: Background, Controls and Mini Map. You can pass your own css styles or use the default styles. If you want to add a plugin to your graph you need to pass it as a children to your React Flow component:
import React, { useState } from 'react';
import ReactFlow, { MiniMap, Controls } from 'react-flow-renderer';
const nodeColor = (node) => {
if (node.type === 'input') return 'blue';
if (node.type === 'output') return 'green';
if (node.type === 'default') return 'red';
return 'gray';
};
const FlowWithPlugins = () => {
return (
<ReactFlow elements={[]} style={{ height: 500 }}>
<MiniMap nodeColor={nodeColor} />
<Controls />
</ReactFlow>
);
};
In the above example we are using the nodeColor property to change the color of displayed nodes inside the mini map. You can adjust the look by using the nodeColor, nodeBorderRadius, maskColor or style properties.

That's it

I hope that I could give you a good overview of React Flow. If you have any questions or feedback, feel free to contact me via mail or twitter or post an issue on Github. Best wishes and stay safe everyone!
Further Reading
webkid logo
webkid GmbH
Kohlfurter Straße 41/43
10999 Berlin
info@webkid.io
+49 30 232 575 450
Imprint
Privacy